This is an automated email from the ASF dual-hosted git repository.
cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 189e8b9d18 add NumericRangeIndex interface and BoundFilter support
(#12830)
189e8b9d18 is described below
commit 189e8b9d18b1f9266215ff4a6811b9b571e78aa0
Author: Clint Wylie <[email protected]>
AuthorDate: Fri Jul 29 18:58:49 2022 -0700
add NumericRangeIndex interface and BoundFilter support (#12830)
add NumericRangeIndex interface and BoundFilter support
changes:
* NumericRangeIndex interface, like LexicographicalRangeIndex but for
numbers
* BoundFilter now uses NumericRangeIndex if comparator is numeric and there
is no extractionFn
* NestedFieldLiteralColumnIndexSupplier.java now supports supplying
NumericRangeIndex for single typed numeric nested literal columns
* better faster stronger and (ever so slightly) more understandable
* more tests, fix bug
* fix style
---
.../benchmark/query/SqlNestedDataBenchmark.java | 14 +-
.../org/apache/druid/query/filter/InDimFilter.java | 2 +-
.../druid/segment/column/NumericRangeIndex.java | 42 +
.../apache/druid/segment/filter/BoundFilter.java | 135 +-
.../NestedFieldLiteralColumnIndexSupplier.java | 276 ++--
.../NestedFieldLiteralColumnIndexSupplierTest.java | 1517 +++++++++++++++++++-
.../sql/calcite/CalciteNestedDataQueryTest.java | 4 +-
7 files changed, 1758 insertions(+), 232 deletions(-)
diff --git
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlNestedDataBenchmark.java
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlNestedDataBenchmark.java
index d41589142d..d719da7dba 100644
---
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlNestedDataBenchmark.java
+++
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlNestedDataBenchmark.java
@@ -165,7 +165,13 @@ public class SqlNestedDataBenchmark
"SELECT JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) FROM foo
WHERE JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) IN (1, 19, 21,
23, 25, 26, 46)",
// 24, 25
"SELECT long2 FROM foo WHERE long2 IN (1, 19, 21, 23, 25, 26, 46) GROUP
BY 1",
- "SELECT JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) FROM foo
WHERE JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) IN (1, 19, 21,
23, 25, 26, 46) GROUP BY 1"
+ "SELECT JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) FROM foo
WHERE JSON_VALUE(nested, '$.nesteder.long2' RETURNING BIGINT) IN (1, 19, 21,
23, 25, 26, 46) GROUP BY 1",
+ // 26, 27
+ "SELECT SUM(long1) FROM foo WHERE double3 < 1005.0 AND double3 > 1000.0",
+ "SELECT SUM(JSON_VALUE(nested, '$.long1' RETURNING BIGINT)) FROM foo
WHERE JSON_VALUE(nested, '$.nesteder.double3' RETURNING DOUBLE) < 1005.0 AND
JSON_VALUE(nested, '$.nesteder.double3' RETURNING DOUBLE) > 1000.0",
+ // 28, 29
+ "SELECT SUM(long1) FROM foo WHERE double3 < 2000.0 AND double3 > 1000.0",
+ "SELECT SUM(JSON_VALUE(nested, '$.long1' RETURNING BIGINT)) FROM foo
WHERE JSON_VALUE(nested, '$.nesteder.double3' RETURNING DOUBLE) < 2000.0 AND
JSON_VALUE(nested, '$.nesteder.double3' RETURNING DOUBLE) > 1000.0"
);
@Param({"5000000"})
@@ -203,7 +209,11 @@ public class SqlNestedDataBenchmark
"22",
"23",
"24",
- "25"
+ "25",
+ "26",
+ "27",
+ "28",
+ "29"
})
private String query;
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 74270b65c5..60e07ee09b 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
@@ -523,7 +523,7 @@ public class InDimFilter extends
AbstractOptimizableDimFilter implements Filter
private final Supplier<DruidFloatPredicate> floatPredicateSupplier;
private final Supplier<DruidDoublePredicate> doublePredicateSupplier;
- InFilterDruidPredicateFactory(
+ public InFilterDruidPredicateFactory(
final ExtractionFn extractionFn,
final ValuesSet values
)
diff --git
a/processing/src/main/java/org/apache/druid/segment/column/NumericRangeIndex.java
b/processing/src/main/java/org/apache/druid/segment/column/NumericRangeIndex.java
new file mode 100644
index 0000000000..bb9bf5c625
--- /dev/null
+++
b/processing/src/main/java/org/apache/druid/segment/column/NumericRangeIndex.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.segment.column;
+
+import javax.annotation.Nullable;
+
+/**
+ * An optimized column value {@link BitmapColumnIndex} provider for
specialized processing of numeric value ranges.
+ * This index does not match null values, union the results of this index with
{@link NullValueIndex} if null values
+ * should be considered part of the value range.
+ */
+public interface NumericRangeIndex
+{
+ /**
+ * Get a {@link BitmapColumnIndex} corresponding to the values supplied in
the specified range. If supplied starting
+ * value is null, the range will begin at the first non-null value in the
underlying value dictionary. If the end
+ * value is null, the range will extend to the last value in the underlying
value dictionary.
+ */
+ BitmapColumnIndex forRange(
+ @Nullable Number startValue,
+ boolean startStrict,
+ @Nullable Number endValue,
+ boolean endStrict
+ );
+}
diff --git
a/processing/src/main/java/org/apache/druid/segment/filter/BoundFilter.java
b/processing/src/main/java/org/apache/druid/segment/filter/BoundFilter.java
index 0c00d31086..b4c1463b07 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/BoundFilter.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/BoundFilter.java
@@ -48,6 +48,7 @@ import
org.apache.druid.segment.column.ColumnIndexCapabilities;
import org.apache.druid.segment.column.ColumnIndexSupplier;
import org.apache.druid.segment.column.LexicographicalRangeIndex;
import org.apache.druid.segment.column.NullValueIndex;
+import org.apache.druid.segment.column.NumericRangeIndex;
import org.apache.druid.segment.vector.VectorColumnSelectorFactory;
import javax.annotation.Nullable;
@@ -75,71 +76,107 @@ public class BoundFilter implements Filter
if (!Filters.checkFilterTuningUseIndex(boundDimFilter.getDimension(),
selector, filterTuning)) {
return null;
}
- if (supportShortCircuit()) {
+ if (supportStringShortCircuit()) {
final ColumnIndexSupplier indexSupplier =
selector.getIndexSupplier(boundDimFilter.getDimension());
if (indexSupplier == null) {
return Filters.makeNullIndex(doesMatchNull(), selector);
}
final LexicographicalRangeIndex rangeIndex =
indexSupplier.as(LexicographicalRangeIndex.class);
- if (rangeIndex == null) {
- // column
- return null;
+ if (rangeIndex != null) {
+ final BitmapColumnIndex rangeBitmaps = rangeIndex.forRange(
+ boundDimFilter.getLower(),
+ boundDimFilter.isLowerStrict(),
+ boundDimFilter.getUpper(),
+ boundDimFilter.isUpperStrict()
+ );
+ // preserve sad backwards compatible behavior where bound filter
matches 'null' if the lower bound is not set
+ if (boundDimFilter.hasLowerBound() &&
!NullHandling.isNullOrEquivalent(boundDimFilter.getLower())) {
+ return rangeBitmaps;
+ } else {
+ return wrapRangeIndexWithNullValueIndex(indexSupplier, rangeBitmaps);
+ }
}
- final BitmapColumnIndex rangeBitmaps = rangeIndex.forRange(
- boundDimFilter.getLower(),
- boundDimFilter.isLowerStrict(),
- boundDimFilter.getUpper(),
- boundDimFilter.isUpperStrict()
- );
- // preserve sad backwards compatible behavior where bound filter matches
'null' if the lower bound is not set
- if (boundDimFilter.hasLowerBound() &&
!NullHandling.isNullOrEquivalent(boundDimFilter.getLower())) {
- return rangeBitmaps;
- } else {
- final NullValueIndex nulls = indexSupplier.as(NullValueIndex.class);
- if (nulls == null) {
- return null;
+ }
+ if (supportNumericShortCircuit()) {
+ final ColumnIndexSupplier indexSupplier =
selector.getIndexSupplier(boundDimFilter.getDimension());
+ if (indexSupplier == null) {
+ return Filters.makeNullIndex(doesMatchNull(), selector);
+ }
+ final NumericRangeIndex rangeIndex =
indexSupplier.as(NumericRangeIndex.class);
+ if (rangeIndex != null) {
+ final Number lower = boundDimFilter.hasLowerBound() ?
Double.parseDouble(boundDimFilter.getLower()) : null;
+ final Number upper = boundDimFilter.hasUpperBound() ?
Double.parseDouble(boundDimFilter.getUpper()) : null;
+ final BitmapColumnIndex rangeBitmaps = rangeIndex.forRange(
+ lower,
+ boundDimFilter.isLowerStrict(),
+ upper,
+ boundDimFilter.isUpperStrict()
+ );
+ // preserve sad backwards compatible behavior where bound filter
matches 'null' if the lower bound is not set
+ if (boundDimFilter.hasLowerBound() &&
!NullHandling.isNullOrEquivalent(boundDimFilter.getLower())) {
+ return rangeBitmaps;
+ } else {
+ return wrapRangeIndexWithNullValueIndex(indexSupplier, rangeBitmaps);
}
- final BitmapColumnIndex nullBitmap = nulls.forNull();
- return new BitmapColumnIndex()
- {
- @Override
- public ColumnIndexCapabilities getIndexCapabilities()
- {
- return
rangeBitmaps.getIndexCapabilities().merge(nullBitmap.getIndexCapabilities());
- }
-
- @Override
- public double estimateSelectivity(int totalRows)
- {
- return Math.min(
- 1.0,
- rangeBitmaps.estimateSelectivity(totalRows) +
nullBitmap.estimateSelectivity(totalRows)
- );
- }
-
- @Override
- public <T> T computeBitmapResult(BitmapResultFactory<T>
bitmapResultFactory)
- {
- return bitmapResultFactory.union(
- ImmutableList.of(
- rangeBitmaps.computeBitmapResult(bitmapResultFactory),
- nullBitmap.computeBitmapResult(bitmapResultFactory)
- )
- );
- }
- };
}
- } else {
- return Filters.makePredicateIndex(boundDimFilter.getDimension(),
selector, getPredicateFactory());
}
+ // fall back to predicate based index if it is available
+ return Filters.makePredicateIndex(boundDimFilter.getDimension(), selector,
getPredicateFactory());
+ }
+
+ @Nullable
+ private BitmapColumnIndex wrapRangeIndexWithNullValueIndex(
+ ColumnIndexSupplier indexSupplier,
+ BitmapColumnIndex rangeIndex
+ )
+ {
+ final NullValueIndex nulls = indexSupplier.as(NullValueIndex.class);
+ if (nulls == null) {
+ return null;
+ }
+ final BitmapColumnIndex nullBitmap = nulls.forNull();
+ return new BitmapColumnIndex()
+ {
+ @Override
+ public ColumnIndexCapabilities getIndexCapabilities()
+ {
+ return
rangeIndex.getIndexCapabilities().merge(nullBitmap.getIndexCapabilities());
+ }
+
+ @Override
+ public double estimateSelectivity(int totalRows)
+ {
+ return Math.min(
+ 1.0,
+ rangeIndex.estimateSelectivity(totalRows) +
nullBitmap.estimateSelectivity(totalRows)
+ );
+ }
+
+ @Override
+ public <T> T computeBitmapResult(BitmapResultFactory<T>
bitmapResultFactory)
+ {
+ return bitmapResultFactory.union(
+ ImmutableList.of(
+ rangeIndex.computeBitmapResult(bitmapResultFactory),
+ nullBitmap.computeBitmapResult(bitmapResultFactory)
+ )
+ );
+ }
+ };
}
- private boolean supportShortCircuit()
+ private boolean supportStringShortCircuit()
{
// Optimization for lexicographic bounds with no extractionFn => binary
search through the index
return
boundDimFilter.getOrdering().equals(StringComparators.LEXICOGRAPHIC) &&
extractionFn == null;
}
+ private boolean supportNumericShortCircuit()
+ {
+ // Optimization for numeric bounds with no extractionFn => binary search
through the index
+ return boundDimFilter.getOrdering().equals(StringComparators.NUMERIC) &&
extractionFn == null;
+ }
+
@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplier.java
b/processing/src/main/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplier.java
index 99df4d99d5..e67ac8ac52 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplier.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplier.java
@@ -35,23 +35,27 @@ import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import org.apache.druid.collections.bitmap.BitmapFactory;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
+import org.apache.druid.common.config.NullHandling;
import org.apache.druid.common.guava.GuavaUtils;
import org.apache.druid.query.BitmapResultFactory;
import org.apache.druid.query.filter.DruidDoublePredicate;
import org.apache.druid.query.filter.DruidLongPredicate;
import org.apache.druid.query.filter.DruidPredicateFactory;
+import org.apache.druid.segment.IntListUtils;
import org.apache.druid.segment.column.BitmapColumnIndex;
import org.apache.druid.segment.column.ColumnIndexSupplier;
import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.DruidPredicateIndex;
import org.apache.druid.segment.column.LexicographicalRangeIndex;
import org.apache.druid.segment.column.NullValueIndex;
+import org.apache.druid.segment.column.NumericRangeIndex;
import org.apache.druid.segment.column.SimpleBitmapColumnIndex;
import org.apache.druid.segment.column.SimpleImmutableBitmapIndex;
import org.apache.druid.segment.column.SimpleImmutableBitmapIterableIndex;
import org.apache.druid.segment.column.StringValueSetIndex;
import org.apache.druid.segment.data.FixedIndexed;
import org.apache.druid.segment.data.GenericIndexed;
+import org.apache.druid.segment.data.Indexed;
import javax.annotation.Nullable;
import java.util.Iterator;
@@ -120,6 +124,8 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
case LONG:
if (clazz.equals(StringValueSetIndex.class)) {
return (T) new NestedLongLiteralValueSetIndex();
+ } else if (clazz.equals(NumericRangeIndex.class)) {
+ return (T) new NestedLongLiteralNumericRangeIndex();
} else if (clazz.equals(DruidPredicateIndex.class)) {
return (T) new NestedLongLiteralPredicateIndex();
}
@@ -127,6 +133,8 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
case DOUBLE:
if (clazz.equals(StringValueSetIndex.class)) {
return (T) new NestedDoubleLiteralValueSetIndex();
+ } else if (clazz.equals(NumericRangeIndex.class)) {
+ return (T) new NestedDoubleLiteralNumericRangeIndex();
} else if (clazz.equals(DruidPredicateIndex.class)) {
return (T) new NestedDoubleLiteralPredicateIndex();
}
@@ -153,47 +161,106 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
return bitmap == null ? bitmapFactory.makeEmptyImmutableBitmap() : bitmap;
}
- private IntIntPair getGlobalRange(
- @Nullable String startValue,
+ /**
+ * Gets a value range from a global dictionary and maps it to a range on the
local {@link #dictionary}.
+ * The starting index of the resulting range is inclusive, while the
endpoint is exclusive [start, end)
+ */
+ private <T> IntIntPair getLocalRangeFromDictionary(
+ @Nullable T startValue,
boolean startStrict,
- @Nullable String endValue,
+ @Nullable T endValue,
boolean endStrict,
- int rangeStart,
- int rangeEnd,
- GlobalIndexGetFunction getFn
+ Indexed<T> globalDictionary,
+ int adjust
)
{
- int startIndex, endIndex;
+ int globalStartIndex, globalEndIndex;
+ int localStartIndex, localEndIndex;
if (startValue == null) {
- startIndex = rangeStart;
+ globalStartIndex = adjust == 0 ? 1 : adjust; // global index 0 is always
the null value
} else {
- final int found = getFn.indexOf(startValue);
+ final int found = globalDictionary.indexOf(startValue);
if (found >= 0) {
- startIndex = startStrict ? found + 1 : found;
+ globalStartIndex = adjust + (startStrict ? found + 1 : found);
} else {
- startIndex = -(found + 1);
+ globalStartIndex = adjust + (-(found + 1));
}
}
+ // with starting global index settled, now lets find starting local index
+ int localFound = dictionary.indexOf(globalStartIndex);
+ if (localFound < 0) {
+ // the first valid global index is not within the local dictionary, so
the insertion point is where we begin
+ localStartIndex = -(localFound + 1);
+ } else {
+ // valid global index in local dictionary, start here
+ localStartIndex = localFound;
+ }
if (endValue == null) {
- endIndex = rangeEnd;
+ globalEndIndex = globalDictionary.size() + adjust;
} else {
- final int found = getFn.indexOf(endValue);
+ final int found = globalDictionary.indexOf(endValue);
if (found >= 0) {
- endIndex = endStrict ? found : found + 1;
+ globalEndIndex = adjust + (endStrict ? found : found + 1);
} else {
- endIndex = -(found + 1);
+ globalEndIndex = adjust + (-(found + 1));
}
}
+ globalEndIndex = Math.max(globalStartIndex, globalEndIndex);
+ // end index is not inclusive, so we find the last value in the local
dictionary that falls within the range
+ int localEndFound = dictionary.indexOf(globalEndIndex - 1);
+ if (localEndFound < 0) {
+ localEndIndex = -localEndFound;
+ } else {
+ // add 1 because the last valid global end value is in the local
dictionary, and end index is exclusive
+ localEndIndex = localEndFound + 1;
+ }
- endIndex = Math.max(startIndex, endIndex);
- return new IntIntImmutablePair(startIndex, endIndex);
+ return new IntIntImmutablePair(localStartIndex,
Math.min(dictionary.size(), localEndIndex));
}
- @FunctionalInterface
- interface GlobalIndexGetFunction
+ private <T> BitmapColumnIndex makeRangeIndex(
+ @Nullable T startValue,
+ boolean startStrict,
+ @Nullable T endValue,
+ boolean endStrict,
+ Indexed<T> globalDictionary,
+ int adjust
+ )
{
- int indexOf(String value);
+ final IntIntPair localRange = getLocalRangeFromDictionary(
+ startValue,
+ startStrict,
+ endValue,
+ endStrict,
+ globalDictionary,
+ adjust
+ );
+ final int startIndex = localRange.leftInt();
+ final int endIndex = localRange.rightInt();
+ return new SimpleImmutableBitmapIterableIndex()
+ {
+ @Override
+ public Iterable<ImmutableBitmap> getBitmapIterable()
+ {
+ return () -> new Iterator<ImmutableBitmap>()
+ {
+ final IntIterator rangeIterator = IntListUtils.fromTo(startIndex,
endIndex).iterator();
+
+ @Override
+ public boolean hasNext()
+ {
+ return rangeIterator.hasNext();
+ }
+
+ @Override
+ public ImmutableBitmap next()
+ {
+ return getBitmap(rangeIterator.nextInt());
+ }
+ };
+ }
+ };
}
private class NestedStringLiteralValueSetIndex implements StringValueSetIndex
@@ -274,7 +341,6 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
private class NestedStringLiteralLexicographicalRangeIndex implements
LexicographicalRangeIndex
{
-
@Override
public BitmapColumnIndex forRange(
@Nullable String startValue,
@@ -283,70 +349,14 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
boolean endStrict
)
{
- return new SimpleImmutableBitmapIterableIndex()
- {
- @Override
- public Iterable<ImmutableBitmap> getBitmapIterable()
- {
- final IntIntPair range = getGlobalRange(
- startValue,
- startStrict,
- endValue,
- endStrict,
- 0,
- globalDictionary.size(),
- globalDictionary::indexOf
- );
- final int start = range.leftInt(), end = range.rightInt();
- // iterates over the range of values in the global dictionary,
mapping to relevant range in the local
- // dictionary, skipping duplicates
- return () -> new Iterator<ImmutableBitmap>()
- {
- int currentGlobalIndex = start;
- // initialize to -1 because findNext uses this field to check for
duplicates, and could legitimately find
- // 0 for the first candidate
- @SuppressWarnings("UnusedAssignment")
- int currentLocalIndex = -1;
- {
- currentLocalIndex = findNext();
- }
-
- private int findNext()
- {
- int candidateLocalIndex =
Math.abs(dictionary.indexOf(currentGlobalIndex));
- while (currentGlobalIndex < end && candidateLocalIndex ==
currentLocalIndex) {
- currentGlobalIndex++;
- candidateLocalIndex =
Math.abs(dictionary.indexOf(currentGlobalIndex));
- }
- if (currentGlobalIndex < end) {
- currentGlobalIndex++;
- return candidateLocalIndex;
- } else {
- return -1;
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return currentLocalIndex != -1;
- }
-
- @Override
- public ImmutableBitmap next()
- {
- int cur = currentLocalIndex;
-
- if (cur == -1) {
- throw new NoSuchElementException();
- }
-
- currentLocalIndex = findNext();
- return getBitmap(cur);
- }
- };
- }
- };
+ return makeRangeIndex(
+ NullHandling.emptyToNullIfNeeded(startValue),
+ startStrict,
+ NullHandling.emptyToNullIfNeeded(endValue),
+ endStrict,
+ globalDictionary,
+ 0
+ );
}
@Override
@@ -363,67 +373,53 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
@Override
public Iterable<ImmutableBitmap> getBitmapIterable()
{
- final IntIntPair stringsRange = getGlobalRange(
+ final IntIntPair range = getLocalRangeFromDictionary(
startValue,
startStrict,
endValue,
endStrict,
- 0,
- globalDictionary.size(),
- globalDictionary::indexOf
+ globalDictionary,
+ 0
);
- // iterates over the range of values in the global dictionary,
mapping to relevant range in the local
- // dictionary, skipping duplicates
+ final int start = range.leftInt(), end = range.rightInt();
return () -> new Iterator<ImmutableBitmap>()
{
- int currentGlobalIndex = stringsRange.leftInt();
- final int end = stringsRange.rightInt();
- // initialize to -1 because findNext uses this field to check for
duplicates, and could legitimately find
- // 0 for the first candidate
- @SuppressWarnings("UnusedAssignment")
- int currentLocalIndex = -1;
+ int currIndex = start;
+ int found;
+
{
- currentLocalIndex = findNext();
+ found = findNext();
}
private int findNext()
{
- int candidateLocalIndex =
Math.abs(dictionary.indexOf(currentGlobalIndex));
- while (currentGlobalIndex < end &&
shouldSkipGlobal(candidateLocalIndex)) {
- currentGlobalIndex++;
- candidateLocalIndex =
Math.abs(dictionary.indexOf(currentGlobalIndex));
+ while (currIndex < end &&
!matcher.apply(globalDictionary.get(dictionary.get(currIndex)))) {
+ currIndex++;
}
- if (currentGlobalIndex < end) {
- currentGlobalIndex++;
- return candidateLocalIndex;
+ if (currIndex < end) {
+ return currIndex++;
} else {
return -1;
}
}
- private boolean shouldSkipGlobal(int candidate)
- {
- return currentLocalIndex == candidate ||
!matcher.apply(globalDictionary.get(currentGlobalIndex));
- }
-
-
@Override
public boolean hasNext()
{
- return currentLocalIndex != -1;
+ return found != -1;
}
@Override
public ImmutableBitmap next()
{
- int cur = currentLocalIndex;
+ int cur = found;
if (cur == -1) {
throw new NoSuchElementException();
}
- currentLocalIndex = findNext();
+ found = findNext();
return getBitmap(cur);
}
};
@@ -492,10 +488,8 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
}
}
-
private class NestedLongLiteralValueSetIndex implements StringValueSetIndex
{
-
@Override
public BitmapColumnIndex forValue(@Nullable String value)
{
@@ -592,6 +586,27 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
}
}
+ private class NestedLongLiteralNumericRangeIndex implements NumericRangeIndex
+ {
+ @Override
+ public BitmapColumnIndex forRange(
+ @Nullable Number startValue,
+ boolean startStrict,
+ @Nullable Number endValue,
+ boolean endStrict
+ )
+ {
+ return makeRangeIndex(
+ startValue != null ? startValue.longValue() : null,
+ startStrict,
+ endValue != null ? endValue.longValue() : null,
+ endStrict,
+ globalLongDictionary,
+ adjustLongId
+ );
+ }
+ }
+
private class NestedLongLiteralPredicateIndex implements DruidPredicateIndex
{
@Override
@@ -658,7 +673,6 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
private class NestedDoubleLiteralValueSetIndex implements StringValueSetIndex
{
-
@Override
public BitmapColumnIndex forValue(@Nullable String value)
{
@@ -755,6 +769,27 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
}
}
+ private class NestedDoubleLiteralNumericRangeIndex implements
NumericRangeIndex
+ {
+ @Override
+ public BitmapColumnIndex forRange(
+ @Nullable Number startValue,
+ boolean startStrict,
+ @Nullable Number endValue,
+ boolean endStrict
+ )
+ {
+ return makeRangeIndex(
+ startValue != null ? startValue.doubleValue() : null,
+ startStrict,
+ endValue != null ? endValue.doubleValue() : null,
+ endStrict,
+ globalDoubleDictionary,
+ adjustDoubleId
+ );
+ }
+ }
+
private class NestedDoubleLiteralPredicateIndex implements
DruidPredicateIndex
{
@Override
@@ -818,7 +853,7 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
}
}
- private abstract class NestedAnyLiteralIndex
+ private abstract class NestedVariantLiteralIndex
{
IntList getIndexes(@Nullable String value)
{
@@ -858,7 +893,7 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
/**
* {@link StringValueSetIndex} but for variant typed nested literal columns
*/
- private class NestedVariantLiteralValueSetIndex extends
NestedAnyLiteralIndex implements StringValueSetIndex
+ private class NestedVariantLiteralValueSetIndex extends
NestedVariantLiteralIndex implements StringValueSetIndex
{
@Override
public BitmapColumnIndex forValue(@Nullable String value)
@@ -937,9 +972,8 @@ public class NestedFieldLiteralColumnIndexSupplier
implements ColumnIndexSupplie
/**
* {@link DruidPredicateIndex} but for variant typed nested literal columns
*/
- private class NestedVariantLiteralPredicateIndex extends
NestedAnyLiteralIndex implements DruidPredicateIndex
+ private class NestedVariantLiteralPredicateIndex extends
NestedVariantLiteralIndex implements DruidPredicateIndex
{
-
@Override
public BitmapColumnIndex forPredicate(DruidPredicateFactory matcherFactory)
{
diff --git
a/processing/src/test/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplierTest.java
b/processing/src/test/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplierTest.java
index c72afd9009..13a451428d 100644
---
a/processing/src/test/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplierTest.java
+++
b/processing/src/test/java/org/apache/druid/segment/nested/NestedFieldLiteralColumnIndexSupplierTest.java
@@ -19,80 +19,1483 @@
package org.apache.druid.segment.nested;
-import junit.framework.TestCase;
+import com.google.common.collect.ImmutableSet;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.collections.bitmap.MutableBitmap;
-import org.apache.druid.collections.bitmap.RoaringBitmapFactory;
+import org.apache.druid.query.BitmapResultFactory;
import org.apache.druid.query.DefaultBitmapResultFactory;
+import org.apache.druid.query.filter.DruidPredicateFactory;
+import org.apache.druid.query.filter.InDimFilter;
import org.apache.druid.segment.column.BitmapColumnIndex;
import org.apache.druid.segment.column.ColumnType;
+import org.apache.druid.segment.column.DruidPredicateIndex;
import org.apache.druid.segment.column.LexicographicalRangeIndex;
+import org.apache.druid.segment.column.NullValueIndex;
+import org.apache.druid.segment.column.NumericRangeIndex;
+import org.apache.druid.segment.column.StringValueSetIndex;
+import org.apache.druid.segment.column.TypeStrategies;
+import org.apache.druid.segment.data.BitmapSerdeFactory;
import org.apache.druid.segment.data.FixedIndexed;
+import org.apache.druid.segment.data.FixedIndexedWriter;
import org.apache.druid.segment.data.GenericIndexed;
-import org.easymock.EasyMock;
+import org.apache.druid.segment.data.GenericIndexedWriter;
+import org.apache.druid.segment.data.RoaringBitmapSerdeFactory;
+import org.apache.druid.segment.serde.Serializer;
+import org.apache.druid.segment.writeout.OnHeapMemorySegmentWriteOutMedium;
+import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
+import org.roaringbitmap.IntIterator;
-public class NestedFieldLiteralColumnIndexSupplierTest extends TestCase
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.WritableByteChannel;
+import java.util.TreeSet;
+
+public class NestedFieldLiteralColumnIndexSupplierTest extends
InitializedNullHandlingTest
{
+ BitmapSerdeFactory roaringFactory = new RoaringBitmapSerdeFactory(null);
+ BitmapResultFactory<ImmutableBitmap> bitmapResultFactory = new
DefaultBitmapResultFactory(
+ roaringFactory.getBitmapFactory()
+ );
+ GenericIndexed<String> globalStrings;
+ FixedIndexed<Long> globalLongs;
+ FixedIndexed<Double> globalDoubles;
+
+ @Before
+ public void setup() throws IOException
+ {
+ ByteBuffer stringBuffer = ByteBuffer.allocate(1 << 12);
+ ByteBuffer longBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer doubleBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+
+ GenericIndexedWriter<String> stringWriter = new GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "strings",
+ GenericIndexed.STRING_STRATEGY
+ );
+ stringWriter.open();
+ stringWriter.write(null);
+ stringWriter.write("a");
+ stringWriter.write("b");
+ stringWriter.write("fo");
+ stringWriter.write("foo");
+ stringWriter.write("fooo");
+ stringWriter.write("z");
+ writeToBuffer(stringBuffer, stringWriter);
+
+ FixedIndexedWriter<Long> longWriter = new FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ TypeStrategies.LONG,
+ ByteOrder.nativeOrder(),
+ Long.BYTES,
+ true
+ );
+ longWriter.open();
+ longWriter.write(1L);
+ longWriter.write(2L);
+ longWriter.write(3L);
+ longWriter.write(5L);
+ longWriter.write(100L);
+ longWriter.write(300L);
+ longWriter.write(9000L);
+ writeToBuffer(longBuffer, longWriter);
+
+ FixedIndexedWriter<Double> doubleWriter = new FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ TypeStrategies.DOUBLE,
+ ByteOrder.nativeOrder(),
+ Double.BYTES,
+ true
+ );
+ doubleWriter.open();
+ doubleWriter.write(1.0);
+ doubleWriter.write(1.1);
+ doubleWriter.write(1.2);
+ doubleWriter.write(2.0);
+ doubleWriter.write(2.5);
+ doubleWriter.write(3.3);
+ doubleWriter.write(6.6);
+ doubleWriter.write(9.9);
+ writeToBuffer(doubleBuffer, doubleWriter);
+
+ globalStrings = GenericIndexed.read(stringBuffer,
GenericIndexed.STRING_STRATEGY);
+ globalLongs = FixedIndexed.read(longBuffer, TypeStrategies.LONG,
ByteOrder.nativeOrder(), Long.BYTES);
+ globalDoubles = FixedIndexed.read(doubleBuffer, TypeStrategies.DOUBLE,
ByteOrder.nativeOrder(), Double.BYTES);
+ }
+
@Test
- public void testRangeValueSkipping()
- {
- FixedIndexed<Integer> localDictionary =
EasyMock.createMock(FixedIndexed.class);
- GenericIndexed<String> stringDictionary =
EasyMock.createMock(GenericIndexed.class);
- FixedIndexed<Long> longDictionary =
EasyMock.createMock(FixedIndexed.class);
- FixedIndexed<Double> doubleDictionary =
EasyMock.createMock(FixedIndexed.class);
- GenericIndexed<ImmutableBitmap> bitmaps =
EasyMock.createMock(GenericIndexed.class);
-
- RoaringBitmapFactory bitmapFactory = new RoaringBitmapFactory();
- MutableBitmap bitmap = bitmapFactory.makeEmptyMutableBitmap();
- bitmap.add(1);
- ImmutableBitmap immutableBitmap =
bitmapFactory.makeImmutableBitmap(bitmap);
- MutableBitmap bitmap2 = bitmapFactory.makeEmptyMutableBitmap();
- bitmap2.add(2);
- ImmutableBitmap immutableBitmap2 =
bitmapFactory.makeImmutableBitmap(bitmap2);
-
- EasyMock.expect(stringDictionary.size()).andReturn(10).times(3);
- EasyMock.expect(longDictionary.size()).andReturn(0).times(1);
- EasyMock.expect(stringDictionary.indexOf("fo")).andReturn(3).times(2);
- EasyMock.expect(stringDictionary.indexOf("fooo")).andReturn(5).times(2);
- EasyMock.expect(stringDictionary.get(3)).andReturn("fo").times(1);
- EasyMock.expect(stringDictionary.get(4)).andReturn("foo").times(1);
- EasyMock.expect(stringDictionary.get(5)).andReturn("fooo").times(1);
- EasyMock.expect(localDictionary.indexOf(3)).andReturn(0).times(2);
- EasyMock.expect(localDictionary.indexOf(4)).andReturn(0).times(2);
- EasyMock.expect(localDictionary.indexOf(5)).andReturn(1).times(2);
- EasyMock.expect(localDictionary.indexOf(6)).andReturn(-2).times(2);
- EasyMock.expect(bitmaps.get(0)).andReturn(immutableBitmap).times(1);
- EasyMock.expect(bitmaps.get(1)).andReturn(immutableBitmap2).times(2);
-
- EasyMock.replay(localDictionary, stringDictionary, longDictionary,
doubleDictionary, bitmaps);
-
- NestedFieldLiteralColumnIndexSupplier indexSupplier = new
NestedFieldLiteralColumnIndexSupplier(
- new NestedLiteralTypeInfo.TypeSet(new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.STRING).getByteValue()),
- bitmapFactory,
- bitmaps,
- localDictionary,
- stringDictionary,
- longDictionary,
- doubleDictionary
+ public void testSingleTypeStringColumnValueSetIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringSupplier();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [b, foo, fooo, z]
+ // column: [foo, b, fooo, b, z, fooo, z, b, b, foo]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("b");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.4, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 7, 8);
+
+ // non-existent in local column
+ columnIndex = valueSetIndex.forValue("fo");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.0, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("b", "fooo", "z")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.8, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 2, 3, 4, 5, 6, 7, 8);
+ }
+
+ @Test
+ public void testSingleTypeStringColumnRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringSupplier();
+
+ LexicographicalRangeIndex rangeIndex =
indexSupplier.as(LexicographicalRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [b, foo, fooo, z]
+ // column: [foo, b, fooo, b, z, fooo, z, b, b, foo]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange("f", true, "g", true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.4, forRange.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 5, 9);
+
+ forRange = rangeIndex.forRange(null, false, "g", true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.8, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 5, 7, 8, 9);
+
+ forRange = rangeIndex.forRange("f", false, null, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange("b", true, "fooo", true);
+ Assert.assertEquals(0.2, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 9);
+
+ forRange = rangeIndex.forRange("b", true, "fooo", false);
+ Assert.assertEquals(0.4, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 5, 9);
+
+ forRange = rangeIndex.forRange(null, true, "fooo", true);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 3, 7, 8, 9);
+
+ forRange = rangeIndex.forRange("b", true, null, false);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange("b", false, null, true);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, true, "fooo", false);
+ Assert.assertEquals(0.8, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 5, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+
+ @Test
+ public void testSingleTypeStringColumnRangeIndexWithPredicate() throws
IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringSupplier();
+
+ LexicographicalRangeIndex rangeIndex =
indexSupplier.as(LexicographicalRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [b, foo, fooo, z]
+ // column: [foo, b, fooo, b, z, fooo, z, b, b, foo]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange(
+ "f",
+ true,
+ "g",
+ true,
+ s -> !"fooo".equals(s)
+ );
+ Assert.assertEquals(0.2, forRange.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 9);
+
+ forRange = rangeIndex.forRange(
+ "f",
+ true,
+ "g",
+ true,
+ s -> "fooo".equals(s)
+ );
+ Assert.assertEquals(0.2, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 5);
+
+ forRange = rangeIndex.forRange(
+ null,
+ false,
+ "z",
+ false,
+ s -> !"fooo".equals(s)
+ );
+ Assert.assertEquals(0.8, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 3, 4, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(
+ null,
+ false,
+ "z",
+ true,
+ s -> !"fooo".equals(s)
+ );
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 3, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(
+ "f",
+ true,
+ null,
+ true,
+ s -> true
+ );
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 6, 9);
+ }
+
+ @Test
+ public void testSingleTypeStringColumnPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringSupplier();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("b", "z"))
+ );
+
+ // 10 rows
+ // local: [b, foo, fooo, z]
+ // column: [foo, b, fooo, b, z, fooo, z, b, b, foo]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.6, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 4, 6, 7, 8);
+ }
+
+ @Test
+ public void testSingleTypeStringColumnWithNullValueIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringWithNullsSupplier();
+
+ NullValueIndex nullIndex = indexSupplier.as(NullValueIndex.class);
+ Assert.assertNotNull(nullIndex);
+
+ // 10 rows
+ // local: [null, b, foo, fooo, z]
+ // column: [foo, null, fooo, b, z, fooo, z, null, null, foo]
+
+ BitmapColumnIndex columnIndex = nullIndex.forNull();
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 7, 8);
+ }
+
+ @Test
+ public void testSingleTypeStringColumnWithNullValueSetIndex() throws
IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringWithNullsSupplier();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [null, b, foo, fooo, z]
+ // column: [foo, null, fooo, b, z, fooo, z, null, null, foo]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("b");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.1, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 3);
+
+ // non-existent in local column
+ columnIndex = valueSetIndex.forValue("fo");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.0, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("b", "fooo", "z")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.5, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 3, 4, 5, 6);
+ }
+
+ @Test
+ public void testSingleValueStringWithNullRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringWithNullsSupplier();
+
+ LexicographicalRangeIndex rangeIndex =
indexSupplier.as(LexicographicalRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [null, b, foo, fooo, z]
+ // column: [foo, null, fooo, b, z, fooo, z, null, null, foo]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange("f", true, "g", true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.4, forRange.estimateSelectivity(10), 0.0);
+
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 5, 9);
+
+ forRange = rangeIndex.forRange(null, false, "g", true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.5, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 3, 5, 9);
+
+ forRange = rangeIndex.forRange("f", false, null, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange("b", true, "fooo", true);
+ Assert.assertEquals(0.2, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 9);
+
+ forRange = rangeIndex.forRange("b", true, "fooo", false);
+ Assert.assertEquals(0.4, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 5, 9);
+
+ forRange = rangeIndex.forRange(null, true, "fooo", true);
+ Assert.assertEquals(0.3, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 3, 9);
+
+ forRange = rangeIndex.forRange("b", true, null, false);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange("b", false, null, true);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 3, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange(null, true, "fooo", false);
+ Assert.assertEquals(0.5, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 3, 5, 9);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 3, 4, 5, 6, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 3, 4, 5, 6, 9);
+ }
+
+ @Test
+ public void testSingleValueStringWithNullPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeStringWithNullsSupplier();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("b", "z"))
+ );
+
+ // 10 rows
+ // local: [null, b, foo, fooo, z]
+ // column: [foo, null, fooo, b, z, fooo, z, null, null, foo]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 3, 4, 6);
+ }
+
+ @Test
+ public void testSingleTypeLongColumnValueSetIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplier();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [1, 3, 100, 300]
+ // column: [100, 1, 300, 1, 3, 3, 100, 300, 300, 1]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("1");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 9);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("1", "300", "700")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.6, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 2, 3, 7, 8, 9);
+ }
+
+ @Test
+ public void testSingleTypeLongColumnRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplier();
+
+ NumericRangeIndex rangeIndex = indexSupplier.as(NumericRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [1, 3, 100, 300]
+ // column: [100, 1, 300, 1, 3, 3, 100, 300, 300, 1]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange(10L, true, 400L, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.5, forRange.estimateSelectivity(10), 0.0);
+
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 6, 7, 8);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+
+ @Test
+ public void testSingleTypeLongColumnPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplier();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("1", "3"))
+ );
+
+ // 10 rows
+ // local: [1, 3, 100, 300]
+ // column: [100, 1, 300, 1, 3, 3, 100, 300, 300, 1]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.5, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 4, 5, 9);
+ }
+
+ @Test
+ public void testSingleTypeLongColumnWithNullValueIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplierWithNull();
+
+ NullValueIndex nullIndex = indexSupplier.as(NullValueIndex.class);
+ Assert.assertNotNull(nullIndex);
+
+ // 10 rows
+ // local: [null, 1, 3, 100, 300]
+ // column: [100, 1, null, 1, 3, null, 100, 300, null, 1]
+
+ BitmapColumnIndex columnIndex = nullIndex.forNull();
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 5, 8);
+ }
+
+ @Test
+ public void testSingleTypeLongColumnWithNullValueSetIndex() throws
IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplierWithNull();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [null, 1, 3, 100, 300]
+ // column: [100, 1, null, 1, 3, null, 100, 300, null, 1]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("3");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.1, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 4);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("1", "3", "300")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.5, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 4, 7, 9);
+ }
+
+ @Test
+ public void testSingleValueLongWithNullRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplierWithNull();
+
+ NumericRangeIndex rangeIndex = indexSupplier.as(NumericRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [null, 1, 3, 100, 300]
+ // column: [100, 1, null, 1, 3, null, 100, 300, null, 1]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange(100, false, 700, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.3, forRange.estimateSelectivity(10), 0.0);
+
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 6, 7);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 3, 4, 6, 7, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 3, 4, 6, 7, 9);
+ }
+
+ @Test
+ public void testSingleValueLongWithNullPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeLongSupplierWithNull();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("3", "100"))
+ );
+
+ // 10 rows
+ // local: [null, 1, 3, 100, 300]
+ // column: [100, 1, null, 1, 3, null, 100, 300, null, 1]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 4, 6);
+ }
+
+ @Test
+ public void testSingleTypeDoubleColumnValueSetIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplier();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, 1.1, 1.2, 3.3, 1.2, 6.6, 3.3, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("1.2");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 4, 7);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("1.2", "3.3", "6.6")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.7, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 3, 4, 5, 6, 7, 9);
+ }
+
+ @Test
+ public void testSingleTypeDoubleColumnRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplier();
+
+ NumericRangeIndex rangeIndex = indexSupplier.as(NumericRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, 1.1, 1.2, 3.3, 1.2, 6.6, 3.3, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange(1.0, true, 5.0, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.9, forRange.estimateSelectivity(10), 0.0);
+
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(1.1, false, 3.3, false);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.9, forRange.estimateSelectivity(10), 0.0);
+
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(1.1, true, 3.3, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 3, 4, 6, 7, 9);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(1.0, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ }
+
+ @Test
+ public void testSingleTypeDoubleColumnPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplier();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("1.2", "3.3", "5.0"))
+ );
+
+ // 10 rows
+ // local: [1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, 1.1, 1.2, 3.3, 1.2, 6.6, 3.3, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.6, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 3, 4, 6, 7, 9);
+ }
+
+ @Test
+ public void testSingleTypeDoubleColumnWithNullValueIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplierWithNull();
+
+ NullValueIndex nullIndex = indexSupplier.as(NullValueIndex.class);
+ Assert.assertNotNull(nullIndex);
+
+ // 10 rows
+ // local: [null, 1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, null, 1.2, null, 1.2, 6.6, null, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex columnIndex = nullIndex.forNull();
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.3, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 6);
+ }
+
+ @Test
+ public void testSingleTypeDoubleColumnWithNullValueSetIndex() throws
IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplierWithNull();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [null, 1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, null, 1.2, null, 1.2, 6.6, null, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("6.6");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.1, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 5);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("1.2", "3.3", "7.7")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.4, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 4, 7, 9);
+ }
+
+ @Test
+ public void testSingleValueDoubleWithNullRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplierWithNull();
+
+ NumericRangeIndex rangeIndex = indexSupplier.as(NumericRangeIndex.class);
+ Assert.assertNotNull(rangeIndex);
+
+ // 10 rows
+ // local: [null, 1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, null, 1.2, null, 1.2, 6.6, null, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex forRange = rangeIndex.forRange(1.1, false, 5.0, true);
+ Assert.assertNotNull(forRange);
+ Assert.assertEquals(0.6, forRange.estimateSelectivity(10), 0.0);
+
+ ImmutableBitmap bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, true, null, true);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 7, 8, 9);
+
+ forRange = rangeIndex.forRange(null, false, null, false);
+ Assert.assertEquals(0.7, forRange.estimateSelectivity(10), 0.0);
+ bitmap = forRange.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 2, 4, 5, 7, 8, 9);
+ }
+
+ @Test
+ public void testSingleValueDoubleWithNullPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeSingleTypeDoubleSupplierWithNull();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("1.2", "3.3"))
);
+ // 10 rows
+ // local: [null, 1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, null, 1.2, null, 1.2, 6.6, null, 1.2, 1.1, 3.3]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.4, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 4, 7, 9);
+ }
+
+ @Test
+ public void testVariantNullValueIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeVariantSupplierWithNull();
+
+ NullValueIndex nullIndex = indexSupplier.as(NullValueIndex.class);
+ Assert.assertNotNull(nullIndex);
+
+ // 10 rows
+ // local: [null, b, z, 1, 300, 1.1, 9.9]
+ // column: [1, b, null, 9.9, 300, 1, z, null, 1.1, b]
+
+ BitmapColumnIndex columnIndex = nullIndex.forNull();
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.2, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 2, 7);
+ }
+
+ @Test
+ public void testVariantValueSetIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeVariantSupplierWithNull();
+
+ StringValueSetIndex valueSetIndex =
indexSupplier.as(StringValueSetIndex.class);
+ Assert.assertNotNull(valueSetIndex);
+
+ // 10 rows
+ // local: [null, b, z, 1, 300, 1.1, 9.9]
+ // column: [1, b, null, 9.9, 300, 1, z, null, 1.1, b]
+
+ BitmapColumnIndex columnIndex = valueSetIndex.forValue("b");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.2, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 9);
+
+ columnIndex = valueSetIndex.forValue("1");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.2, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 0, 5);
+
+ columnIndex = valueSetIndex.forValue("1.1");
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.1, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 8);
+
+ // set index
+ columnIndex = valueSetIndex.forSortedValues(new
TreeSet<>(ImmutableSet.of("b", "300", "9.9", "1.6")));
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.4, columnIndex.estimateSelectivity(10), 0.0);
+ bitmap = columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 4, 9);
+ }
+
+ @Test
+ public void testVariantRangeIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeVariantSupplierWithNull();
+
LexicographicalRangeIndex rangeIndex =
indexSupplier.as(LexicographicalRangeIndex.class);
+ Assert.assertNull(rangeIndex);
+
+ NumericRangeIndex numericRangeIndex =
indexSupplier.as(NumericRangeIndex.class);
+ Assert.assertNull(numericRangeIndex);
+ }
+
+ @Test
+ public void testVariantPredicateIndex() throws IOException
+ {
+ NestedFieldLiteralColumnIndexSupplier indexSupplier =
makeVariantSupplierWithNull();
+
+ DruidPredicateIndex predicateIndex =
indexSupplier.as(DruidPredicateIndex.class);
+ Assert.assertNotNull(predicateIndex);
+ DruidPredicateFactory predicateFactory = new
InDimFilter.InFilterDruidPredicateFactory(
+ null,
+ new InDimFilter.ValuesSet(ImmutableSet.of("b", "z", "9.9", "300"))
+ );
+
+ // 10 rows
+ // local: [null, b, z, 1, 300, 1.1, 9.9]
+ // column: [1, b, null, 9.9, 300, 1, z, null, 1.1, b]
+
+ BitmapColumnIndex columnIndex =
predicateIndex.forPredicate(predicateFactory);
+ Assert.assertNotNull(columnIndex);
+ Assert.assertEquals(0.5, columnIndex.estimateSelectivity(10), 0.0);
+ ImmutableBitmap bitmap =
columnIndex.computeBitmapResult(bitmapResultFactory);
+ checkBitmap(bitmap, 1, 3, 4, 6, 9);
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier makeSingleTypeStringSupplier()
throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [b, foo, fooo, z]
+ // column: [foo, b, fooo, b, z, fooo, z, b, b, foo]
+
+ // b
+ localDictionaryWriter.write(2);
+ bitmapWriter.write(fillBitmap(1, 3, 7, 8));
+
+ // foo
+ localDictionaryWriter.write(4);
+ bitmapWriter.write(fillBitmap(0, 9));
+
+ // fooo
+ localDictionaryWriter.write(5);
+ bitmapWriter.write(fillBitmap(2, 5));
+
+ // z
+ localDictionaryWriter.write(6);
+ bitmapWriter.write(fillBitmap(4, 6));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.STRING).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier
makeSingleTypeStringWithNullsSupplier() throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [null, b, foo, fooo, z]
+ // column: [foo, null, fooo, b, z, fooo, z, null, null, foo]
+
+ // null
+ localDictionaryWriter.write(0);
+ bitmapWriter.write(fillBitmap(1, 7, 8));
+
+ // b
+ localDictionaryWriter.write(2);
+ bitmapWriter.write(fillBitmap(3));
+
+ // foo
+ localDictionaryWriter.write(4);
+ bitmapWriter.write(fillBitmap(0, 9));
+
+ // fooo
+ localDictionaryWriter.write(5);
+ bitmapWriter.write(fillBitmap(2, 5));
+
+ // z
+ localDictionaryWriter.write(6);
+ bitmapWriter.write(fillBitmap(4, 6));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.STRING).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier makeSingleTypeLongSupplier()
throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [1, 3, 100, 300]
+ // column: [100, 1, 300, 1, 3, 3, 100, 300, 300, 1]
+
+ // 1
+ localDictionaryWriter.write(7);
+ bitmapWriter.write(fillBitmap(1, 3, 9));
+
+ // 3
+ localDictionaryWriter.write(9);
+ bitmapWriter.write(fillBitmap(4, 5));
+
+ // 100
+ localDictionaryWriter.write(11);
+ bitmapWriter.write(fillBitmap(0, 6));
+
+ // 300
+ localDictionaryWriter.write(12);
+ bitmapWriter.write(fillBitmap(2, 7, 8));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.LONG).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier
makeSingleTypeLongSupplierWithNull() throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [null, 1, 3, 100, 300]
+ // column: [100, 1, null, 1, 3, null, 100, 300, null, 1]
+
+ // null
+ localDictionaryWriter.write(0);
+ bitmapWriter.write(fillBitmap(2, 5, 8));
+
+ // 1
+ localDictionaryWriter.write(7);
+ bitmapWriter.write(fillBitmap(1, 3, 9));
+
+ // 3
+ localDictionaryWriter.write(9);
+ bitmapWriter.write(fillBitmap(4));
+
+ // 100
+ localDictionaryWriter.write(11);
+ bitmapWriter.write(fillBitmap(0, 6));
+
+ // 300
+ localDictionaryWriter.write(12);
+ bitmapWriter.write(fillBitmap(7));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.LONG).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier makeSingleTypeDoubleSupplier()
throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, 1.1, 1.2, 3.3, 1.2, 6.6, 3.3, 1.2, 1.1, 3.3]
+
+ // 1.1
+ localDictionaryWriter.write(15);
+ bitmapWriter.write(fillBitmap(0, 1, 8));
+
+ // 1.2
+ localDictionaryWriter.write(16);
+ bitmapWriter.write(fillBitmap(2, 4, 7));
+
+ // 3.3
+ localDictionaryWriter.write(19);
+ bitmapWriter.write(fillBitmap(3, 6, 9));
+
+ // 6.6
+ localDictionaryWriter.write(20);
+ bitmapWriter.write(fillBitmap(5));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.DOUBLE).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier
makeSingleTypeDoubleSupplierWithNull() throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [null, 1.1, 1.2, 3.3, 6.6]
+ // column: [1.1, null, 1.2, null, 1.2, 6.6, null, 1.2, 1.1, 3.3]
+
+ // null
+ localDictionaryWriter.write(0);
+ bitmapWriter.write(fillBitmap(1, 3, 6));
+
+ // 1.1
+ localDictionaryWriter.write(15);
+ bitmapWriter.write(fillBitmap(0, 8));
+
+ // 1.2
+ localDictionaryWriter.write(16);
+ bitmapWriter.write(fillBitmap(2, 4, 7));
+
+ // 3.3
+ localDictionaryWriter.write(19);
+ bitmapWriter.write(fillBitmap(9));
+
+ // 6.6
+ localDictionaryWriter.write(20);
+ bitmapWriter.write(fillBitmap(5));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new
NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.DOUBLE).getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private NestedFieldLiteralColumnIndexSupplier makeVariantSupplierWithNull()
throws IOException
+ {
+ ByteBuffer localDictionaryBuffer = ByteBuffer.allocate(1 <<
12).order(ByteOrder.nativeOrder());
+ ByteBuffer bitmapsBuffer = ByteBuffer.allocate(1 << 12);
+
+ FixedIndexedWriter<Integer> localDictionaryWriter = new
FixedIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES,
+ true
+ );
+ localDictionaryWriter.open();
+ GenericIndexedWriter<ImmutableBitmap> bitmapWriter = new
GenericIndexedWriter<>(
+ new OnHeapMemorySegmentWriteOutMedium(),
+ "bitmaps",
+ roaringFactory.getObjectStrategy()
+ );
+ bitmapWriter.setObjectsNotSorted();
+ bitmapWriter.open();
+
+ // 10 rows
+ // globals: [
+ // [null, a, b, fo, foo, fooo, z],
+ // [1, 2, 3, 5, 100, 300, 9000],
+ // [1.0, 1.1, 1.2, 2.0, 2.5, 3.3, 6.6, 9.9]
+ // ]
+ // local: [null, b, z, 1, 300, 1.1, 9.9]
+ // column: [1, b, null, 9.9, 300, 1, z, null, 1.1, b]
+
+ // null
+ localDictionaryWriter.write(0);
+ bitmapWriter.write(fillBitmap(2, 7));
+
+ // b
+ localDictionaryWriter.write(2);
+ bitmapWriter.write(fillBitmap(1, 9));
+
+ // z
+ localDictionaryWriter.write(6);
+ bitmapWriter.write(fillBitmap(6));
+
+ // 1
+ localDictionaryWriter.write(7);
+ bitmapWriter.write(fillBitmap(0, 5));
+
+ // 300
+ localDictionaryWriter.write(12);
+ bitmapWriter.write(fillBitmap(4));
+
+ // 1.1
+ localDictionaryWriter.write(15);
+ bitmapWriter.write(fillBitmap(8));
+
+ // 9.9
+ localDictionaryWriter.write(21);
+ bitmapWriter.write(fillBitmap(3));
+
+ writeToBuffer(localDictionaryBuffer, localDictionaryWriter);
+ writeToBuffer(bitmapsBuffer, bitmapWriter);
+
+ FixedIndexed<Integer> dictionary = FixedIndexed.read(
+ localDictionaryBuffer,
+ NestedDataColumnSerializer.INT_TYPE_STRATEGY,
+ ByteOrder.nativeOrder(),
+ Integer.BYTES
+ );
+
+ GenericIndexed<ImmutableBitmap> bitmaps =
GenericIndexed.read(bitmapsBuffer, roaringFactory.getObjectStrategy());
+
+ return new NestedFieldLiteralColumnIndexSupplier(
+ new NestedLiteralTypeInfo.TypeSet(
+ new NestedLiteralTypeInfo.MutableTypeSet().add(ColumnType.STRING)
+ .add(ColumnType.LONG)
+ .add(ColumnType.DOUBLE)
+ .getByteValue()
+ ),
+ roaringFactory.getBitmapFactory(),
+ bitmaps,
+ dictionary,
+ globalStrings,
+ globalLongs,
+ globalDoubles
+ );
+ }
+
+ private ImmutableBitmap fillBitmap(int... rows)
+ {
+ MutableBitmap bitmap =
roaringFactory.getBitmapFactory().makeEmptyMutableBitmap();
+ for (int i : rows) {
+ bitmap.add(i);
+ }
+ return roaringFactory.getBitmapFactory().makeImmutableBitmap(bitmap);
+ }
+
+ void checkBitmap(ImmutableBitmap bitmap, int... expectedRows)
+ {
+ IntIterator iterator = bitmap.iterator();
+ for (int i : expectedRows) {
+ Assert.assertTrue(iterator.hasNext());
+ Assert.assertEquals(i, iterator.next());
+ }
+ Assert.assertFalse(iterator.hasNext());
+ }
+
+ static void writeToBuffer(ByteBuffer buffer, Serializer serializer) throws
IOException
+ {
+ WritableByteChannel channel = new WritableByteChannel()
+ {
+ @Override
+ public int write(ByteBuffer src)
+ {
+ int size = src.remaining();
+ buffer.put(src);
+ return size;
+ }
+
+ @Override
+ public boolean isOpen()
+ {
+ return true;
+ }
+
+ @Override
+ public void close()
+ {
+ }
+ };
- BitmapColumnIndex columnIndex = rangeIndex.forRange("fo", false, "fooo",
false);
- DefaultBitmapResultFactory defaultBitmapResultFactory = new
DefaultBitmapResultFactory(bitmapFactory);
- ImmutableBitmap result =
columnIndex.computeBitmapResult(defaultBitmapResultFactory);
- Assert.assertEquals(2, result.size());
- Assert.assertTrue(result.get(1));
- Assert.assertTrue(result.get(2));
-
- // predicate skips first index
- columnIndex = rangeIndex.forRange("fo", false, "fooo", false,
"fooo"::equals);
- result = columnIndex.computeBitmapResult(defaultBitmapResultFactory);
- Assert.assertEquals(1, result.size());
- Assert.assertTrue(result.get(2));
- EasyMock.verify(localDictionary, stringDictionary, longDictionary,
doubleDictionary, bitmaps);
+ serializer.writeTo(channel, null);
+ buffer.position(0);
}
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
index ea3c66d11d..182ef9ab95 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
@@ -852,7 +852,6 @@ public class CalciteNestedDataQueryTest extends
BaseCalciteQueryTest
.build()
),
ImmutableList.of(
- new Object[]{NullHandling.defaultStringValue(), 4L},
new Object[]{"100", 2L}
)
);
@@ -954,6 +953,7 @@ public class CalciteNestedDataQueryTest extends
BaseCalciteQueryTest
.build()
),
ImmutableList.of(
+ new Object[]{NullHandling.defaultStringValue(), 4L},
new Object[]{"100", 2L}
)
);
@@ -1052,7 +1052,6 @@ public class CalciteNestedDataQueryTest extends
BaseCalciteQueryTest
.build()
),
ImmutableList.of(
- new Object[]{NullHandling.defaultStringValue(), 4L},
new Object[]{"2.02", 2L}
)
);
@@ -1154,6 +1153,7 @@ public class CalciteNestedDataQueryTest extends
BaseCalciteQueryTest
.build()
),
ImmutableList.of(
+ new Object[]{NullHandling.defaultStringValue(), 4L},
new Object[]{"2.02", 2L}
)
);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]