This is an automated email from the ASF dual-hosted git repository.
ankitsultana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 7f60f131603 Early short circuit with AND & OR optimizations (#16583)
7f60f131603 is described below
commit 7f60f1316030059b538d299c91e056b29735c609
Author: Shreyaa Sharma <[email protected]>
AuthorDate: Sat Sep 20 01:37:36 2025 +0530
Early short circuit with AND & OR optimizations (#16583)
---
.../apache/pinot/core/common/BlockDocIdSet.java | 16 ++++++++++-
.../pinot/core/operator/docidsets/AndDocIdSet.java | 5 ++++
.../core/operator/docidsets/BitmapDocIdSet.java | 11 ++++++++
.../pinot/core/operator/docidsets/OrDocIdSet.java | 5 ++++
.../docidsets/RangelessBitmapDocIdSet.java | 10 ++++++-
...pDocIdSet.java => ShortCircuitingDocIdSet.java} | 30 ++++++++++++--------
.../core/operator/docidsets/SortedDocIdSet.java | 8 ++++++
.../core/operator/filter/AndFilterOperator.java | 16 ++++++++++-
.../operator/filter/CombinedFilterOperator.java | 7 ++++-
.../core/operator/filter/OrFilterOperator.java | 16 ++++++++++-
.../operator/filter/AndFilterOperatorTest.java | 31 +++++++++++++++++++++
.../core/operator/filter/OrFilterOperatorTest.java | 30 ++++++++++++++++++++
.../apache/pinot/queries/H3IndexQueriesTest.java | 32 ++++++++++++++++++++--
13 files changed, 198 insertions(+), 19 deletions(-)
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/common/BlockDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/common/BlockDocIdSet.java
index dec522db9a6..0de8790e0e5 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/common/BlockDocIdSet.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/common/BlockDocIdSet.java
@@ -21,10 +21,12 @@ package org.apache.pinot.core.common;
import org.apache.pinot.core.operator.blocks.FilterBlock;
import org.apache.pinot.core.operator.dociditerators.AndDocIdIterator;
import org.apache.pinot.core.operator.dociditerators.BitmapDocIdIterator;
+import org.apache.pinot.core.operator.dociditerators.EmptyDocIdIterator;
import org.apache.pinot.core.operator.dociditerators.OrDocIdIterator;
import
org.apache.pinot.core.operator.dociditerators.RangelessBitmapDocIdIterator;
import org.apache.pinot.core.operator.dociditerators.ScanBasedDocIdIterator;
import org.apache.pinot.core.operator.docidsets.BitmapDocIdSet;
+import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
import org.apache.pinot.core.operator.docidsets.RangelessBitmapDocIdSet;
import org.apache.pinot.segment.spi.Constants;
import org.roaringbitmap.RoaringBitmapWriter;
@@ -48,12 +50,21 @@ public interface BlockDocIdSet {
*/
long getNumEntriesScannedInFilter();
+
+
+ /**
+ * Returns an optimized version of this DocIdSet, potentially returning
EmptyDocIdSet or MatchAllDocIdSet
+ * when appropriate, following the same pattern as filter operators.
+ */
+ default BlockDocIdSet getOptimizedDocIdSet() {
+ return this;
+ }
+
/**
* For scan-based FilterBlockDocIdSet, pre-scans the documents and returns a
non-scan-based FilterBlockDocIdSet.
*/
default BlockDocIdSet toNonScanDocIdSet() {
BlockDocIdIterator docIdIterator = iterator();
-
// NOTE: AND and OR DocIdIterator might contain scan-based DocIdIterator
// TODO: This scan is not counted in the execution stats
if (docIdIterator instanceof ScanBasedDocIdIterator || docIdIterator
instanceof AndDocIdIterator
@@ -75,6 +86,9 @@ public interface BlockDocIdSet {
if (docIdIterator instanceof BitmapDocIdIterator) {
return new BitmapDocIdSet((BitmapDocIdIterator) docIdIterator);
}
+ if (docIdIterator instanceof EmptyDocIdIterator) {
+ return EmptyDocIdSet.getInstance();
+ }
return this;
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/AndDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/AndDocIdSet.java
index 64ec2816aaa..a2a7c3294d2 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/AndDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/AndDocIdSet.java
@@ -196,4 +196,9 @@ public final class AndDocIdSet implements BlockDocIdSet {
}
return _numEntriesScannedInFilter + numEntriesScannedForScanBasedDocIdSets;
}
+
+ @Override
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ return this;
+ }
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/BitmapDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/BitmapDocIdSet.java
index 6abf65545b0..24b8b8d5034 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/BitmapDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/BitmapDocIdSet.java
@@ -24,13 +24,16 @@ import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
public class BitmapDocIdSet implements BlockDocIdSet {
+ private final ImmutableRoaringBitmap _bitmap;
private final BitmapDocIdIterator _iterator;
public BitmapDocIdSet(ImmutableRoaringBitmap docIds, int numDocs) {
+ _bitmap = docIds;
_iterator = new BitmapDocIdIterator(docIds, numDocs);
}
public BitmapDocIdSet(BitmapDocIdIterator iterator) {
+ _bitmap = null;
_iterator = iterator;
}
@@ -43,4 +46,12 @@ public class BitmapDocIdSet implements BlockDocIdSet {
public long getNumEntriesScannedInFilter() {
return 0L;
}
+
+ @Override
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ if (_bitmap != null && _bitmap.isEmpty()) {
+ return EmptyDocIdSet.getInstance();
+ }
+ return this;
+ }
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/OrDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/OrDocIdSet.java
index 87f464d0bca..3eb68212b1d 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/OrDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/OrDocIdSet.java
@@ -138,4 +138,9 @@ public final class OrDocIdSet implements BlockDocIdSet {
}
return _numEntriesScannedInFilter + numEntriesScannedForScanBasedDocIdSets;
}
+
+ @Override
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ return this;
+ }
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
index 20fb0af6f57..3f8932c3325 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
@@ -27,7 +27,7 @@ public class RangelessBitmapDocIdSet implements BlockDocIdSet
{
private final RangelessBitmapDocIdIterator _iterator;
public RangelessBitmapDocIdSet(ImmutableRoaringBitmap docIds) {
- _iterator = new RangelessBitmapDocIdIterator(docIds);
+ this(new RangelessBitmapDocIdIterator(docIds));
}
public RangelessBitmapDocIdSet(RangelessBitmapDocIdIterator iterator) {
@@ -43,4 +43,12 @@ public class RangelessBitmapDocIdSet implements
BlockDocIdSet {
public long getNumEntriesScannedInFilter() {
return 0L;
}
+
+ @Override
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ if (_iterator.getDocIds().isEmpty()) {
+ return EmptyDocIdSet.getInstance();
+ }
+ return this;
+ }
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/ShortCircuitingDocIdSet.java
similarity index 56%
copy from
pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
copy to
pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/ShortCircuitingDocIdSet.java
index 20fb0af6f57..89ac37c3883 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/RangelessBitmapDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/ShortCircuitingDocIdSet.java
@@ -18,29 +18,35 @@
*/
package org.apache.pinot.core.operator.docidsets;
+import org.apache.pinot.core.common.BlockDocIdIterator;
import org.apache.pinot.core.common.BlockDocIdSet;
-import
org.apache.pinot.core.operator.dociditerators.RangelessBitmapDocIdIterator;
-import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+import org.apache.pinot.core.operator.dociditerators.EmptyDocIdIterator;
-public class RangelessBitmapDocIdSet implements BlockDocIdSet {
- private final RangelessBitmapDocIdIterator _iterator;
+/**
+ * A DocIdSet used for early short-circuiting that behaves like an empty set
+ * while preserving the number of entries scanned in filters up to the
+ * short-circuit point.
+ */
+public final class ShortCircuitingDocIdSet implements BlockDocIdSet {
+ private final long _numEntriesScannedInFilter;
- public RangelessBitmapDocIdSet(ImmutableRoaringBitmap docIds) {
- _iterator = new RangelessBitmapDocIdIterator(docIds);
+ public ShortCircuitingDocIdSet(long numEntriesScannedInFilter) {
+ _numEntriesScannedInFilter = numEntriesScannedInFilter;
}
- public RangelessBitmapDocIdSet(RangelessBitmapDocIdIterator iterator) {
- _iterator = iterator;
+ @Override
+ public BlockDocIdIterator iterator() {
+ return EmptyDocIdIterator.getInstance();
}
@Override
- public RangelessBitmapDocIdIterator iterator() {
- return _iterator;
+ public long getNumEntriesScannedInFilter() {
+ return _numEntriesScannedInFilter;
}
@Override
- public long getNumEntriesScannedInFilter() {
- return 0L;
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ return EmptyDocIdSet.getInstance();
}
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/SortedDocIdSet.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/SortedDocIdSet.java
index 280f9daeb99..ad39d6dc643 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/SortedDocIdSet.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/SortedDocIdSet.java
@@ -42,4 +42,12 @@ public final class SortedDocIdSet implements BlockDocIdSet {
public long getNumEntriesScannedInFilter() {
return 0L;
}
+
+ @Override
+ public BlockDocIdSet getOptimizedDocIdSet() {
+ if (_docIdRanges.isEmpty()) {
+ return EmptyDocIdSet.getInstance();
+ }
+ return this;
+ }
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/AndFilterOperator.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/AndFilterOperator.java
index 94545d88890..e47cff90589 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/AndFilterOperator.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/AndFilterOperator.java
@@ -30,6 +30,7 @@ import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
import org.apache.pinot.core.operator.docidsets.NotDocIdSet;
import org.apache.pinot.core.operator.docidsets.OrDocIdSet;
+import org.apache.pinot.core.operator.docidsets.ShortCircuitingDocIdSet;
import org.apache.pinot.spi.trace.Tracing;
import org.roaringbitmap.buffer.BufferFastAggregation;
import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
@@ -52,8 +53,21 @@ public class AndFilterOperator extends BaseFilterOperator {
protected BlockDocIdSet getTrues() {
Tracing.activeRecording().setNumChildren(_filterOperators.size());
List<BlockDocIdSet> blockDocIdSets = new
ArrayList<>(_filterOperators.size());
+ long totalEntriesScanned = 0L;
for (BaseFilterOperator filterOperator : _filterOperators) {
- blockDocIdSets.add(filterOperator.getTrues());
+ BlockDocIdSet blockDocIdSet = filterOperator.getTrues();
+ BlockDocIdSet optimizedDocIdSet = blockDocIdSet.getOptimizedDocIdSet();
+ totalEntriesScanned += blockDocIdSet.getNumEntriesScannedInFilter();
+ if (optimizedDocIdSet instanceof EmptyDocIdSet) {
+ return new ShortCircuitingDocIdSet(totalEntriesScanned);
+ }
+ if (optimizedDocIdSet instanceof MatchAllDocIdSet) {
+ continue;
+ }
+ blockDocIdSets.add(optimizedDocIdSet);
+ }
+ if (blockDocIdSets.isEmpty()) {
+ return new MatchAllDocIdSet(_numDocs);
}
return new AndDocIdSet(blockDocIdSets, _queryOptions);
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/CombinedFilterOperator.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/CombinedFilterOperator.java
index b9aeb1c99d1..b6a535237d1 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/CombinedFilterOperator.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/CombinedFilterOperator.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import org.apache.pinot.core.common.BlockDocIdSet;
import org.apache.pinot.core.operator.docidsets.AndDocIdSet;
+import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
import org.apache.pinot.spi.trace.Tracing;
@@ -62,7 +63,11 @@ public class CombinedFilterOperator extends
BaseFilterOperator {
protected BlockDocIdSet getTrues() {
Tracing.activeRecording().setNumChildren(2);
BlockDocIdSet mainFilterDocIdSet =
_mainFilterOperator.nextBlock().getNonScanFilterBLockDocIdSet();
+ BlockDocIdSet optimizedMainFilterDocIdSet =
mainFilterDocIdSet.getOptimizedDocIdSet();
+ if (optimizedMainFilterDocIdSet instanceof EmptyDocIdSet) {
+ return EmptyDocIdSet.getInstance();
+ }
BlockDocIdSet subFilterDocIdSet =
_subFilterOperator.nextBlock().getBlockDocIdSet();
- return new AndDocIdSet(Arrays.asList(mainFilterDocIdSet,
subFilterDocIdSet), _queryOptions);
+ return new AndDocIdSet(Arrays.asList(optimizedMainFilterDocIdSet,
subFilterDocIdSet), _queryOptions);
}
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/OrFilterOperator.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/OrFilterOperator.java
index 9f8477f96d5..1aa635d3fc6 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/OrFilterOperator.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/OrFilterOperator.java
@@ -29,6 +29,7 @@ import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
import org.apache.pinot.core.operator.docidsets.NotDocIdSet;
import org.apache.pinot.core.operator.docidsets.OrDocIdSet;
+import org.apache.pinot.core.operator.docidsets.ShortCircuitingDocIdSet;
import org.apache.pinot.spi.trace.Tracing;
import org.roaringbitmap.buffer.BufferFastAggregation;
import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
@@ -51,8 +52,21 @@ public class OrFilterOperator extends BaseFilterOperator {
protected BlockDocIdSet getTrues() {
Tracing.activeRecording().setNumChildren(_filterOperators.size());
List<BlockDocIdSet> blockDocIdSets = new
ArrayList<>(_filterOperators.size());
+ long totalEntriesScanned = 0L;
for (BaseFilterOperator filterOperator : _filterOperators) {
- blockDocIdSets.add(filterOperator.getTrues());
+ BlockDocIdSet blockDocIdSet = filterOperator.getTrues();
+ BlockDocIdSet optimizedDocIdSet = blockDocIdSet.getOptimizedDocIdSet();
+ totalEntriesScanned += blockDocIdSet.getNumEntriesScannedInFilter();
+ if (optimizedDocIdSet instanceof MatchAllDocIdSet) {
+ return new MatchAllDocIdSet(_numDocs);
+ }
+ if (optimizedDocIdSet instanceof EmptyDocIdSet) {
+ continue;
+ }
+ blockDocIdSets.add(optimizedDocIdSet);
+ }
+ if (blockDocIdSets.isEmpty()) {
+ return new ShortCircuitingDocIdSet(totalEntriesScanned);
}
return new OrDocIdSet(blockDocIdSets, _numDocs);
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/AndFilterOperatorTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/AndFilterOperatorTest.java
index 230a3ead557..5976ca8efa4 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/AndFilterOperatorTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/AndFilterOperatorTest.java
@@ -24,6 +24,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.pinot.core.common.BlockDocIdIterator;
+import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
+import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
import org.apache.pinot.segment.spi.Constants;
import org.roaringbitmap.buffer.MutableRoaringBitmap;
import org.testng.Assert;
@@ -234,4 +236,33 @@ public class AndFilterOperatorTest {
ImmutableList.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
Assert.assertEquals(TestUtils.getDocIds(andFilterOperator.getFalses()),
Collections.emptyList());
}
+
+ @Test
+ public void testAndWithEmptyFilterEarlyTermination() {
+ int numDocs = 10;
+ int[] regularDocIds = new int[]{1, 2, 3};
+ int[] emptyDocIds = new int[0];
+
+ AndFilterOperator andFilterOperator = new AndFilterOperator(
+ Arrays.asList(
+ new TestFilterOperator(regularDocIds, numDocs),
+ new TestFilterOperator(emptyDocIds, numDocs)
+ ), null, numDocs, false);
+
+ Assert.assertEquals((andFilterOperator.getTrues()).getOptimizedDocIdSet(),
EmptyDocIdSet.getInstance());
+ }
+
+ @Test
+ public void testAndWithOnlyMatchAllFilterEarlyTermination() {
+ int numDocs = 10;
+ int numDocs2 = 50;
+
+ AndFilterOperator andFilterOperator = new AndFilterOperator(
+ Arrays.asList(
+ new MatchAllFilterOperator(numDocs),
+ new MatchAllFilterOperator(numDocs2)
+ ), null, numDocs, false);
+
+ Assert.assertTrue(andFilterOperator.getTrues() instanceof
MatchAllDocIdSet);
+ }
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/OrFilterOperatorTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/OrFilterOperatorTest.java
index b1c4aac1f80..f98384dd38b 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/OrFilterOperatorTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/OrFilterOperatorTest.java
@@ -27,6 +27,8 @@ import java.util.List;
import java.util.TreeSet;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.pinot.core.common.BlockDocIdIterator;
+import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
+import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
import org.apache.pinot.segment.spi.Constants;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -181,4 +183,32 @@ public class OrFilterOperatorTest {
Assert.assertEquals(TestUtils.getDocIds(orFilterOperator.getTrues()),
Collections.emptyList());
Assert.assertEquals(TestUtils.getDocIds(orFilterOperator.getFalses()),
Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
}
+
+ @Test
+ public void testOrWithMatchAllFilterEarlyTermination() {
+ int numDocs = 10;
+ int[] regularDocIds = new int[]{1, 2, 3};
+
+ OrFilterOperator orFilterOperator = new OrFilterOperator(
+ Arrays.asList(
+ new TestFilterOperator(regularDocIds, numDocs),
+ new MatchAllFilterOperator(numDocs)
+ ), null, numDocs, false);
+
+ Assert.assertTrue((orFilterOperator.getTrues()).getOptimizedDocIdSet()
instanceof MatchAllDocIdSet);
+ }
+
+ @Test
+ public void testOrWithOnlyEmptyFilterEarlyTermination() {
+ int numDocs = 10;
+ int[] emptyDocIds = new int[0];
+
+ OrFilterOperator orFilterOperator = new OrFilterOperator(
+ Arrays.asList(
+ new TestFilterOperator(emptyDocIds, numDocs),
+ new TestFilterOperator(emptyDocIds, numDocs)
+ ), null, numDocs, false);
+
+ Assert.assertTrue(orFilterOperator.getTrues().getOptimizedDocIdSet()
instanceof EmptyDocIdSet);
+ }
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/H3IndexQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/H3IndexQueriesTest.java
index f8ff4661bb5..eae07caf846 100644
--- a/pinot-core/src/test/java/org/apache/pinot/queries/H3IndexQueriesTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/queries/H3IndexQueriesTest.java
@@ -380,12 +380,12 @@ public class H3IndexQueriesTest extends BaseQueriesTest {
}
@Test
- public void queryStContainsWithMultipleFilters()
+ public void queryStContainsWithMultipleFiltersFirstFilterEmpty()
throws Exception {
List<GenericRow> records = new ArrayList<>(1);
addRecord(records, -122.0007277, 37.5005785);
setUp(records);
- // Test point is closed to border of a polygon but outside.
+ // Test point is close to border of a polygon but outside.
String query = "SELECT COUNT(*) FROM testTable WHERE
ST_Contains(ST_GeomFromText('POLYGON ((\n"
+ " -122.0008564 37.5004316, \n"
+ " -121.9991291 37.5005168, \n"
@@ -399,6 +399,34 @@ public class H3IndexQueriesTest extends BaseQueriesTest {
+ " -122.0001268 37.4993506, \n"
+ " -122.0008564 37.5004316))'), h3Column_geometry) = 0";
+ AggregationOperator aggregationOperator = getOperator(query);
+ AggregationResultsBlock resultsBlock = aggregationOperator.nextBlock();
+
QueriesTestUtils.testInnerSegmentExecutionStatistics(aggregationOperator.getExecutionStatistics(),
0, 1, 0, 1);
+ List<Object> aggregationResult = resultsBlock.getResults();
+ Assert.assertNotNull(aggregationResult);
+ Assert.assertEquals((long) aggregationResult.get(0), 0);
+ }
+
+ @Test
+ public void queryStContainsWithMultipleFiltersSecondFilterEmpty()
+ throws Exception {
+ List<GenericRow> records = new ArrayList<>(1);
+ addRecord(records, -122.0007277, 37.5005785);
+ setUp(records);
+ // Test point is close to border of a polygon but outside.
+ String query = "SELECT COUNT(*) FROM testTable WHERE
ST_Contains(ST_GeomFromText('POLYGON ((\n"
+ + " -122.0008564 37.5004316, \n"
+ + " -121.9991291 37.5005168, \n"
+ + " -121.9990325 37.4995294, \n"
+ + " -122.0001268 37.4993506, \n"
+ + " -122.0008564 37.5004316))'), h3Column_geometry) = 0
AND "
+ + " ST_Contains(ST_GeomFromText('POLYGON (( \n"
+ + " -122.0008564 37.5004316, \n"
+ + " -121.9991291 37.5005168, \n"
+ + " -121.9990325 37.4995294, \n"
+ + " -122.0001268 37.4993506, \n"
+ + " -122.0008564 37.5004316))'), h3Column_geometry) = 1";
+
AggregationOperator aggregationOperator = getOperator(query);
AggregationResultsBlock resultsBlock = aggregationOperator.nextBlock();
QueriesTestUtils.testInnerSegmentExecutionStatistics(aggregationOperator.getExecutionStatistics(),
0, 2, 0, 1);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]