From d8306720d2d3af139788c9204ee2c8e524aa6db3 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Tue, 2 Jan 2024 15:30:23 -0800 Subject: [PATCH 1/3] Fix ColumnSelectorColumnIndexSelector#getColumnCapabilities. It was using virtualColumns.getColumnCapabilities, which only returns capabilities for virtual columns, not regular columns. The effect of this is that expression filters (and in some cases, arrayContainsElement filters) would build value matchers rather than use indexes. I think this has been like this since #12315, which added the getColumnCapabilities method to BitmapIndexSelector, and included the same implementation as exists in the code today. This error is easy to make due to the design of virtualColumns.getColumnCapabilities, so to help avoid it in the future, this patch renames the method to getColumnCapabilitiesWithoutFallback to emphasize that it does not return capabilities for regular columns. --- .../LazilyDecoratedRowsAndColumns.java | 17 ++--- .../ColumnSelectorColumnIndexSelector.java | 2 +- .../QueryableIndexColumnSelectorFactory.java | 6 +- .../apache/druid/segment/VirtualColumns.java | 11 ++- ...IncrementalIndexColumnSelectorFactory.java | 6 +- ...yableIndexVectorColumnSelectorFactory.java | 5 +- ...ColumnSelectorColumnIndexSelectorTest.java | 68 +++++++++++++++++-- .../ExpressionVectorSelectorsTest.java | 2 +- .../segment/virtual/VirtualColumnsTest.java | 20 +++--- 9 files changed, 92 insertions(+), 45 deletions(-) diff --git a/processing/src/main/java/org/apache/druid/query/rowsandcols/LazilyDecoratedRowsAndColumns.java b/processing/src/main/java/org/apache/druid/query/rowsandcols/LazilyDecoratedRowsAndColumns.java index 3e938eb2d9d8..81c3d179ba0b 100644 --- a/processing/src/main/java/org/apache/druid/query/rowsandcols/LazilyDecoratedRowsAndColumns.java +++ b/processing/src/main/java/org/apache/druid/query/rowsandcols/LazilyDecoratedRowsAndColumns.java @@ -246,18 +246,15 @@ private Pair materializeStorageAdapter(StorageAdapter as) final RowSignature.Builder sigBob = RowSignature.builder(); for (String col : cols) { - ColumnCapabilities capabilities; - capabilities = columnSelectorFactory.getColumnCapabilities(col); + final ColumnCapabilities capabilities; + if (virtualColumns != null) { + capabilities = virtualColumns.getColumnCapabilitiesWithFallback(columnSelectorFactory, col); + } else { + capabilities = columnSelectorFactory.getColumnCapabilities(col); + } + if (capabilities != null) { sigBob.add(col, capabilities.toColumnType()); - continue; - } - if (virtualColumns != null) { - capabilities = virtualColumns.getColumnCapabilities(columnSelectorFactory, col); - if (capabilities != null) { - sigBob.add(col, capabilities.toColumnType()); - continue; - } } } final RowSignature signature = sigBob.build(); diff --git a/processing/src/main/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelector.java b/processing/src/main/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelector.java index 62d2870371b9..184138b0ea85 100644 --- a/processing/src/main/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelector.java +++ b/processing/src/main/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelector.java @@ -99,6 +99,6 @@ private boolean isVirtualColumn(final String columnName) @Override public ColumnCapabilities getColumnCapabilities(String column) { - return virtualColumns.getColumnCapabilities(columnSelector, column); + return virtualColumns.getColumnCapabilitiesWithFallback(columnSelector, column); } } diff --git a/processing/src/main/java/org/apache/druid/segment/QueryableIndexColumnSelectorFactory.java b/processing/src/main/java/org/apache/druid/segment/QueryableIndexColumnSelectorFactory.java index 30f37a5f9d42..887f74368aa8 100644 --- a/processing/src/main/java/org/apache/druid/segment/QueryableIndexColumnSelectorFactory.java +++ b/processing/src/main/java/org/apache/druid/segment/QueryableIndexColumnSelectorFactory.java @@ -178,10 +178,6 @@ public long getRowId() @Nullable public ColumnCapabilities getColumnCapabilities(String columnName) { - if (virtualColumns.exists(columnName)) { - return virtualColumns.getColumnCapabilities(columnCache, columnName); - } - - return columnCache.getColumnCapabilities(columnName); + return virtualColumns.getColumnCapabilitiesWithFallback(columnCache, columnName); } } diff --git a/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java b/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java index be8775662629..a72efc21651c 100644 --- a/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java +++ b/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java @@ -394,8 +394,11 @@ public VectorObjectSelector makeVectorObjectSelector( return virtualColumn.makeVectorObjectSelector(columnName, columnSelector, offset); } + /** + * Get capabilities for the virtual column "columnName". If columnName is not a virtual column, returns null. + */ @Nullable - public ColumnCapabilities getColumnCapabilities(ColumnInspector inspector, String columnName) + public ColumnCapabilities getColumnCapabilitiesWithoutFallback(ColumnInspector inspector, String columnName) { final VirtualColumn virtualColumn = getVirtualColumn(columnName); if (virtualColumn != null) { @@ -405,10 +408,14 @@ public ColumnCapabilities getColumnCapabilities(ColumnInspector inspector, Strin } } + /** + * Get capabilities for the column "columnName". If columnName is not a virtual column, delegates to the + * provided {@link ColumnInspector}. + */ @Nullable public ColumnCapabilities getColumnCapabilitiesWithFallback(ColumnInspector inspector, String columnName) { - final ColumnCapabilities virtualColumnCapabilities = getColumnCapabilities(inspector, columnName); + final ColumnCapabilities virtualColumnCapabilities = getColumnCapabilitiesWithoutFallback(inspector, columnName); if (virtualColumnCapabilities != null) { return virtualColumnCapabilities; } else { diff --git a/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndexColumnSelectorFactory.java b/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndexColumnSelectorFactory.java index 92e80f3d7038..45d081c8b916 100644 --- a/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndexColumnSelectorFactory.java +++ b/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndexColumnSelectorFactory.java @@ -127,12 +127,8 @@ public ColumnValueSelector makeColumnValueSelector(String columnName) @Nullable public ColumnCapabilities getColumnCapabilities(String columnName) { - if (virtualColumns.exists(columnName)) { - return virtualColumns.getColumnCapabilities(adapter, columnName); - } - // Use adapter.getColumnCapabilities instead of index.getCapabilities (see note in IncrementalIndexStorageAdapater) - return adapter.getColumnCapabilities(columnName); + return virtualColumns.getColumnCapabilitiesWithFallback(adapter, columnName); } @Nullable diff --git a/processing/src/main/java/org/apache/druid/segment/vector/QueryableIndexVectorColumnSelectorFactory.java b/processing/src/main/java/org/apache/druid/segment/vector/QueryableIndexVectorColumnSelectorFactory.java index 04a676060c3e..79d31ee479d8 100644 --- a/processing/src/main/java/org/apache/druid/segment/vector/QueryableIndexVectorColumnSelectorFactory.java +++ b/processing/src/main/java/org/apache/druid/segment/vector/QueryableIndexVectorColumnSelectorFactory.java @@ -251,9 +251,6 @@ public VectorObjectSelector makeObjectSelector(final String columnName) @Override public ColumnCapabilities getColumnCapabilities(final String columnName) { - if (virtualColumns.exists(columnName)) { - return virtualColumns.getColumnCapabilities(columnCache, columnName); - } - return columnCache.getColumnCapabilities(columnName); + return virtualColumns.getColumnCapabilitiesWithFallback(columnCache, columnName); } } diff --git a/processing/src/test/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelectorTest.java b/processing/src/test/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelectorTest.java index 4065a15a0472..1da27d43315f 100644 --- a/processing/src/test/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelectorTest.java +++ b/processing/src/test/java/org/apache/druid/segment/ColumnSelectorColumnIndexSelectorTest.java @@ -22,11 +22,13 @@ import org.apache.druid.collections.bitmap.BitmapFactory; import org.apache.druid.collections.bitmap.ImmutableBitmap; import org.apache.druid.query.DefaultBitmapResultFactory; +import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ColumnIndexSupplier; import org.apache.druid.segment.column.ColumnType; import org.apache.druid.segment.column.StringUtf8DictionaryEncodedColumn; +import org.apache.druid.segment.column.ValueType; import org.apache.druid.segment.index.BitmapColumnIndex; import org.apache.druid.segment.index.semantic.DictionaryEncodedStringValueIndex; import org.apache.druid.segment.index.semantic.StringValueSetIndexes; @@ -40,6 +42,7 @@ public class ColumnSelectorColumnIndexSelectorTest { private static final String STRING_DICTIONARY_COLUMN_NAME = "string"; private static final String NON_STRING_DICTIONARY_COLUMN_NAME = "not-string"; + private static final String NONEXISTENT_COLUMN_NAME = "nonexistent"; BitmapFactory bitmapFactory; VirtualColumns virtualColumns; @@ -52,13 +55,26 @@ public class ColumnSelectorColumnIndexSelectorTest public void setup() { bitmapFactory = EasyMock.createMock(BitmapFactory.class); - virtualColumns = EasyMock.createMock(VirtualColumns.class); + virtualColumns = VirtualColumns.EMPTY; index = EasyMock.createMock(ColumnSelector.class); indexSelector = new ColumnSelectorColumnIndexSelector(bitmapFactory, virtualColumns, index); indexSupplier = EasyMock.createMock(ColumnIndexSupplier.class); - EasyMock.expect(virtualColumns.getVirtualColumn(STRING_DICTIONARY_COLUMN_NAME)).andReturn(null).anyTimes(); - EasyMock.expect(virtualColumns.getVirtualColumn(NON_STRING_DICTIONARY_COLUMN_NAME)).andReturn(null).anyTimes(); + EasyMock.expect(index.getColumnCapabilities(STRING_DICTIONARY_COLUMN_NAME)) + .andReturn(new ColumnCapabilitiesImpl().setType(ColumnType.STRING) + .setHasMultipleValues(false) + .setDictionaryEncoded(true)) + .anyTimes(); + + EasyMock.expect(index.getColumnCapabilities(NON_STRING_DICTIONARY_COLUMN_NAME)) + .andReturn(new ColumnCapabilitiesImpl().setType(ColumnType.STRING) + .setHasMultipleValues(false) + .setDictionaryEncoded(false)) + .anyTimes(); + + EasyMock.expect(index.getColumnCapabilities(NONEXISTENT_COLUMN_NAME)) + .andReturn(null) + .anyTimes(); ColumnHolder holder = EasyMock.createMock(ColumnHolder.class); EasyMock.expect(index.getColumnHolder(STRING_DICTIONARY_COLUMN_NAME)).andReturn(holder).anyTimes(); @@ -82,7 +98,9 @@ public void setup() EasyMock.expect(valueIndex.getBitmap(0)).andReturn(someBitmap).anyTimes(); EasyMock.expect(someIndex.forValue("foo")).andReturn(columnIndex).anyTimes(); - EasyMock.expect(columnIndex.computeBitmapResult(EasyMock.anyObject(), EasyMock.eq(false))).andReturn(someBitmap).anyTimes(); + EasyMock.expect(columnIndex.computeBitmapResult(EasyMock.anyObject(), EasyMock.eq(false))) + .andReturn(someBitmap) + .anyTimes(); ColumnHolder nonStringHolder = EasyMock.createMock(ColumnHolder.class); EasyMock.expect(index.getColumnHolder(NON_STRING_DICTIONARY_COLUMN_NAME)).andReturn(nonStringHolder).anyTimes(); @@ -96,7 +114,18 @@ public void setup() .setHasBitmapIndexes(true) ).anyTimes(); - EasyMock.replay(bitmapFactory, virtualColumns, index, indexSupplier, holder, stringColumn, nonStringHolder, someIndex, columnIndex, valueIndex, someBitmap); + EasyMock.replay( + bitmapFactory, + index, + indexSupplier, + holder, + stringColumn, + nonStringHolder, + someIndex, + columnIndex, + valueIndex, + someBitmap + ); } @Test @@ -116,7 +145,7 @@ public void testStringDictionaryUseIndex() false ); Assert.assertNotNull(valueBitmap); - EasyMock.verify(bitmapFactory, virtualColumns, index, indexSupplier); + EasyMock.verify(bitmapFactory, index, indexSupplier); } @Test @@ -130,6 +159,31 @@ public void testNonStringDictionaryDoNotUseIndex() StringValueSetIndexes valueIndex = supplier.as(StringValueSetIndexes.class); Assert.assertNull(valueIndex); - EasyMock.verify(bitmapFactory, virtualColumns, index, indexSupplier); + EasyMock.verify(bitmapFactory, index, indexSupplier); + } + + @Test + public void testStringDictionaryGetColumnCapabilities() + { + final ColumnCapabilities capabilities = indexSelector.getColumnCapabilities(STRING_DICTIONARY_COLUMN_NAME); + Assert.assertEquals(ValueType.STRING, capabilities.getType()); + Assert.assertEquals(ColumnCapabilities.Capable.FALSE, capabilities.hasMultipleValues()); + Assert.assertEquals(ColumnCapabilities.Capable.TRUE, capabilities.isDictionaryEncoded()); + } + + @Test + public void testNonStringDictionaryGetColumnCapabilities() + { + final ColumnCapabilities capabilities = indexSelector.getColumnCapabilities(NON_STRING_DICTIONARY_COLUMN_NAME); + Assert.assertEquals(ValueType.STRING, capabilities.getType()); + Assert.assertEquals(ColumnCapabilities.Capable.FALSE, capabilities.hasMultipleValues()); + Assert.assertEquals(ColumnCapabilities.Capable.FALSE, capabilities.isDictionaryEncoded()); + } + + @Test + public void testNonexistentColumnGetColumnCapabilities() + { + final ColumnCapabilities capabilities = indexSelector.getColumnCapabilities(NONEXISTENT_COLUMN_NAME); + Assert.assertNull(capabilities); } } diff --git a/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java b/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java index 570177d83105..8bb14cd0d222 100644 --- a/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java +++ b/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java @@ -238,7 +238,7 @@ public static void sanityTestVectorizedExpressionSelectors( null ); - ColumnCapabilities capabilities = virtualColumns.getColumnCapabilities(storageAdapter, "v"); + ColumnCapabilities capabilities = virtualColumns.getColumnCapabilitiesWithoutFallback(storageAdapter, "v"); int rowCount = 0; if (capabilities.isDictionaryEncoded().isTrue()) { diff --git a/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java b/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java index e13807e07e2a..81f63898716d 100644 --- a/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java +++ b/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java @@ -119,9 +119,9 @@ public void testGetColumnCapabilitiesNilBase() { final VirtualColumns virtualColumns = makeVirtualColumns(); final ColumnInspector baseInspector = column -> null; - Assert.assertEquals(ValueType.FLOAT, virtualColumns.getColumnCapabilities(baseInspector, "expr").getType()); - Assert.assertEquals(ValueType.LONG, virtualColumns.getColumnCapabilities(baseInspector, "expr2").getType()); - Assert.assertNull(virtualColumns.getColumnCapabilities(baseInspector, REAL_COLUMN_NAME)); + Assert.assertEquals(ValueType.FLOAT, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "expr").getType()); + Assert.assertEquals(ValueType.LONG, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "expr2").getType()); + Assert.assertNull(virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, REAL_COLUMN_NAME)); } @Test @@ -135,9 +135,9 @@ public void testGetColumnCapabilitiesDoubleBase() return null; } }; - Assert.assertEquals(ValueType.FLOAT, virtualColumns.getColumnCapabilities(baseInspector, "expr").getType()); - Assert.assertEquals(ValueType.DOUBLE, virtualColumns.getColumnCapabilities(baseInspector, "expr2").getType()); - Assert.assertNull(virtualColumns.getColumnCapabilities(baseInspector, REAL_COLUMN_NAME)); + Assert.assertEquals(ValueType.FLOAT, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "expr").getType()); + Assert.assertEquals(ValueType.DOUBLE, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "expr2").getType()); + Assert.assertNull(virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, REAL_COLUMN_NAME)); } @Test @@ -519,10 +519,10 @@ public ColumnCapabilities getColumnCapabilities(String column) final ExpressionVirtualColumn expr2 = new ExpressionVirtualColumn("v3", "v0 * x", null, TestExprMacroTable.INSTANCE); final VirtualColumns virtualColumns = VirtualColumns.create(ImmutableList.of(v0, v1, expr1, expr2)); - Assert.assertEquals(ColumnType.STRING, virtualColumns.getColumnCapabilities(baseInspector, "v0").toColumnType()); - Assert.assertEquals(ColumnType.LONG, virtualColumns.getColumnCapabilities(baseInspector, "v1").toColumnType()); - Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilities(baseInspector, "v2").toColumnType()); - Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilities(baseInspector, "v3").toColumnType()); + Assert.assertEquals(ColumnType.STRING, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "v0").toColumnType()); + Assert.assertEquals(ColumnType.LONG, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "v1").toColumnType()); + Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "v2").toColumnType()); + Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilitiesWithoutFallback(baseInspector, "v3").toColumnType()); Assert.assertTrue(virtualColumns.canVectorize(baseInspector)); } From 0f73a8a1d7411841f843fd9ae9b6a492e9f93025 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Tue, 2 Jan 2024 15:38:57 -0800 Subject: [PATCH 2/3] Make getColumnCapabilitiesWithoutFallback package-private. --- .../apache/druid/segment/VirtualColumns.java | 3 ++- .../{virtual => }/VirtualColumnsTest.java | 18 +++--------------- .../virtual/ExpressionVectorSelectorsTest.java | 2 +- 3 files changed, 6 insertions(+), 17 deletions(-) rename processing/src/test/java/org/apache/druid/segment/{virtual => }/VirtualColumnsTest.java (96%) diff --git a/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java b/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java index a72efc21651c..5560d10d4edf 100644 --- a/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java +++ b/processing/src/main/java/org/apache/druid/segment/VirtualColumns.java @@ -396,9 +396,10 @@ public VectorObjectSelector makeVectorObjectSelector( /** * Get capabilities for the virtual column "columnName". If columnName is not a virtual column, returns null. + * Package-private since production callers want {@link #getColumnCapabilitiesWithFallback(ColumnInspector, String)}. */ @Nullable - public ColumnCapabilities getColumnCapabilitiesWithoutFallback(ColumnInspector inspector, String columnName) + ColumnCapabilities getColumnCapabilitiesWithoutFallback(ColumnInspector inspector, String columnName) { final VirtualColumn virtualColumn = getVirtualColumn(columnName); if (virtualColumn != null) { diff --git a/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java b/processing/src/test/java/org/apache/druid/segment/VirtualColumnsTest.java similarity index 96% rename from processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java rename to processing/src/test/java/org/apache/druid/segment/VirtualColumnsTest.java index 81f63898716d..71d9adbd0170 100644 --- a/processing/src/test/java/org/apache/druid/segment/virtual/VirtualColumnsTest.java +++ b/processing/src/test/java/org/apache/druid/segment/VirtualColumnsTest.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.druid.segment.virtual; +package org.apache.druid.segment; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; @@ -31,26 +31,14 @@ import org.apache.druid.query.filter.DruidPredicateFactory; import org.apache.druid.query.filter.ValueMatcher; import org.apache.druid.query.monomorphicprocessing.RuntimeShapeInspector; -import org.apache.druid.segment.BaseFloatColumnValueSelector; -import org.apache.druid.segment.BaseLongColumnValueSelector; -import org.apache.druid.segment.BaseObjectColumnValueSelector; -import org.apache.druid.segment.ColumnInspector; -import org.apache.druid.segment.ColumnSelectorFactory; -import org.apache.druid.segment.ColumnValueSelector; -import org.apache.druid.segment.DimensionDictionarySelector; -import org.apache.druid.segment.DimensionSelector; -import org.apache.druid.segment.DimensionSelectorUtils; -import org.apache.druid.segment.IdLookup; -import org.apache.druid.segment.TestHelper; -import org.apache.druid.segment.TestLongColumnSelector; -import org.apache.druid.segment.VirtualColumn; -import org.apache.druid.segment.VirtualColumns; import org.apache.druid.segment.column.ColumnCapabilities; import org.apache.druid.segment.column.ColumnCapabilitiesImpl; import org.apache.druid.segment.column.ColumnType; import org.apache.druid.segment.column.ValueType; import org.apache.druid.segment.data.IndexedInts; import org.apache.druid.segment.data.ZeroIndexedInts; +import org.apache.druid.segment.virtual.ExpressionVirtualColumn; +import org.apache.druid.segment.virtual.NestedFieldVirtualColumn; import org.apache.druid.testing.InitializedNullHandlingTest; import org.junit.Assert; import org.junit.Rule; diff --git a/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java b/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java index 8bb14cd0d222..cd8b78ed1f97 100644 --- a/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java +++ b/processing/src/test/java/org/apache/druid/segment/virtual/ExpressionVectorSelectorsTest.java @@ -238,7 +238,7 @@ public static void sanityTestVectorizedExpressionSelectors( null ); - ColumnCapabilities capabilities = virtualColumns.getColumnCapabilitiesWithoutFallback(storageAdapter, "v"); + ColumnCapabilities capabilities = virtualColumns.getColumnCapabilitiesWithFallback(storageAdapter, "v"); int rowCount = 0; if (capabilities.isDictionaryEncoded().isTrue()) { From 327fb869846f60d000974090b9aa0e504475cc49 Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Tue, 2 Jan 2024 19:11:31 -0800 Subject: [PATCH 3/3] Fix expression filter bitmap usage. --- .../org/apache/druid/segment/filter/ExpressionFilter.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/processing/src/main/java/org/apache/druid/segment/filter/ExpressionFilter.java b/processing/src/main/java/org/apache/druid/segment/filter/ExpressionFilter.java index c284c8e6bcef..78c9b6758e2f 100644 --- a/processing/src/main/java/org/apache/druid/segment/filter/ExpressionFilter.java +++ b/processing/src/main/java/org/apache/druid/segment/filter/ExpressionFilter.java @@ -344,6 +344,7 @@ public boolean isNullInputUnknown() */ private DruidPredicateFactory getBitmapPredicateFactory(@Nullable ColumnCapabilities inputCapabilites) { + final boolean isNullUnknown = expr.get().eval(InputBindings.nilBindings()).value() == null; return new DruidPredicateFactory() { @Override @@ -431,6 +432,12 @@ public Predicate makeArrayPredicate(@Nullable TypeSignature ).asBoolean(); } + @Override + public boolean isNullInputUnknown() + { + return isNullUnknown; + } + // The hashcode and equals are to make SubclassesMustOverrideEqualsAndHashCodeTest stop complaining.. // DruidPredicateFactory currently doesn't really need equals or hashcode since 'toString' method that is actually // called when testing equality of DimensionPredicateFilter, so it's the truly required method, but that seems