diff --git a/processing/src/main/java/org/apache/druid/query/filter/InDimFilter.java b/processing/src/main/java/org/apache/druid/query/filter/InDimFilter.java index 577e25573574..adba7f859357 100644 --- a/processing/src/main/java/org/apache/druid/query/filter/InDimFilter.java +++ b/processing/src/main/java/org/apache/druid/query/filter/InDimFilter.java @@ -432,14 +432,18 @@ private byte[] computeCacheKey() sortedValues = sortedValuesList; } + // Hash all values, in sorted order, as their length followed by their content. final Hasher hasher = Hashing.sha256().newHasher(); for (String v : sortedValues) { if (v == null) { - hasher.putInt(0); + // Encode null as length -1, no content. + hasher.putInt(-1); } else { + hasher.putInt(v.length()); hasher.putString(v, StandardCharsets.UTF_8); } } + return new CacheKeyBuilder(DimFilterUtils.IN_CACHE_ID) .appendString(dimension) .appendByte(DimFilterUtils.STRING_SEPARATOR) diff --git a/processing/src/test/java/org/apache/druid/query/filter/InDimFilterTest.java b/processing/src/test/java/org/apache/druid/query/filter/InDimFilterTest.java index 3bc53f62e53c..25c27d449eef 100644 --- a/processing/src/test/java/org/apache/druid/query/filter/InDimFilterTest.java +++ b/processing/src/test/java/org/apache/druid/query/filter/InDimFilterTest.java @@ -97,6 +97,19 @@ public void testGetCacheKeyReturningSameKeyForValuesOfDifferentOrders() Assert.assertArrayEquals(dimFilter1.getCacheKey(), dimFilter2.getCacheKey()); } + @Test + public void testGetCacheKeyForNullVsEmptyString() + { + final InDimFilter inDimFilter1 = new InDimFilter("dimTest", Arrays.asList(null, "abc"), null); + final InDimFilter inDimFilter2 = new InDimFilter("dimTest", Arrays.asList("", "abc"), null); + + if (NullHandling.sqlCompatible()) { + Assert.assertFalse(Arrays.equals(inDimFilter1.getCacheKey(), inDimFilter2.getCacheKey())); + } else { + Assert.assertArrayEquals(inDimFilter1.getCacheKey(), inDimFilter2.getCacheKey()); + } + } + @Test public void testGetCacheKeyReturningSameKeyForSetsOfDifferentTypesAndComparators() { @@ -119,6 +132,22 @@ public void testGetCacheKeyDifferentKeysForListOfStringsAndSingleStringOfLists() Assert.assertFalse(Arrays.equals(inDimFilter1.getCacheKey(), inDimFilter2.getCacheKey())); } + @Test + public void testGetCacheKeyDifferentKeysForNullAndFourZeroChars() + { + final InDimFilter inDimFilter1 = new InDimFilter("dimTest", Arrays.asList(null, "abc"), null); + final InDimFilter inDimFilter2 = new InDimFilter("dimTest", Arrays.asList("\0\0\0\0", "abc"), null); + Assert.assertFalse(Arrays.equals(inDimFilter1.getCacheKey(), inDimFilter2.getCacheKey())); + } + + @Test + public void testGetCacheKeyDifferentKeysWhenStringBoundariesMove() + { + final InDimFilter inDimFilter1 = new InDimFilter("dimTest", Arrays.asList("bar", "foo"), null); + final InDimFilter inDimFilter2 = new InDimFilter("dimTest", Arrays.asList("barf", "oo"), null); + Assert.assertFalse(Arrays.equals(inDimFilter1.getCacheKey(), inDimFilter2.getCacheKey())); + } + @Test public void testGetCacheKeyDifferentKeysForListOfStringsAndSingleStringOfListsWithExtractFn() {