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]

Reply via email to