This is an automated email from the ASF dual-hosted git repository.

xiangfu0 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 41b8c20a8b6 Normalize empty filter results to EmptyDocIdSet when they 
are built (#19684)
41b8c20a8b6 is described below

commit 41b8c20a8b6f98f0f3b8326fe7eeace627f8bd84
Author: Xiaotian (Jackie) Jiang <[email protected]>
AuthorDate: Wed Sep 30 00:21:19 2026 -0700

    Normalize empty filter results to EmptyDocIdSet when they are built (#19684)
    
    Replace the lazy `BlockDocIdSet#getOptimizedDocIdSet` check with doc id 
sets that are normalized when they are
    built, so an empty result is always an `EmptyDocIdSet` and every parent can 
recognize it by type:
    - `BitmapDocIdSet`, `RangelessBitmapDocIdSet` and `SortedDocIdSet` get 
`create` factories that return an
      `EmptyDocIdSet` for an empty input. The index-based filter operators and 
`toNonScanDocIdSet` use them.
    - `EmptyDocIdSet` keeps the number of entries scanned before the result was 
found empty, replacing
      `ShortCircuitingDocIdSet`. `EmptyDocIdSet.unscanned()` (was 
`getInstance()`) is the shared instance for a result
      found without scanning.
    - `BitmapDocIdSet` takes an optional scan count, replacing the anonymous 
subclasses in the H3 and legacy range index
      filter operators.
    - `BaseColumnFilterOperator` passes an empty match through its 
null-handling wrappers instead of wrapping it in an
      AND / OR doc id set.
    - `TestFilterOperator` moves to test sources.
    
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .../apache/pinot/core/common/BlockDocIdSet.java    | 19 +++-----
 .../pinot/core/operator/docidsets/AndDocIdSet.java |  5 ---
 .../core/operator/docidsets/BitmapDocIdSet.java    | 37 ++++++++++------
 .../core/operator/docidsets/EmptyDocIdSet.java     | 19 +++++---
 .../pinot/core/operator/docidsets/OrDocIdSet.java  |  5 ---
 .../docidsets/RangelessBitmapDocIdSet.java         | 18 ++++----
 .../docidsets/ShortCircuitingDocIdSet.java         | 50 ----------------------
 .../core/operator/docidsets/SortedDocIdSet.java    | 13 +++---
 .../core/operator/filter/AndFilterOperator.java    | 14 +++---
 .../operator/filter/BaseColumnFilterOperator.java  |  8 +++-
 .../core/operator/filter/BaseFilterOperator.java   | 12 +++---
 .../operator/filter/BitmapBasedFilterOperator.java |  6 +--
 .../operator/filter/CombinedFilterOperator.java    |  7 ++-
 .../core/operator/filter/EmptyFilterOperator.java  |  2 +-
 .../filter/ExactVectorScanFilterOperator.java      |  2 +-
 .../operator/filter/ExpressionFilterOperator.java  |  2 +-
 .../filter/H3InclusionIndexFilterOperator.java     |  7 +--
 .../operator/filter/H3IndexFilterOperator.java     | 11 ++---
 .../filter/InvertedIndexFilterOperator.java        | 10 ++---
 .../operator/filter/JsonMatchFilterOperator.java   |  2 +-
 .../core/operator/filter/NotFilterOperator.java    |  2 +-
 .../core/operator/filter/OrFilterOperator.java     | 14 +++---
 .../filter/RangeIndexBasedFilterOperator.java      | 13 ++----
 .../filter/SortedIndexBasedFilterOperator.java     |  8 ++--
 .../operator/filter/TextMatchFilterOperator.java   |  5 ++-
 .../filter/VectorRadiusFilterOperator.java         |  2 +-
 .../filter/VectorSimilarityFilterOperator.java     |  2 +-
 .../startree/operator/StarTreeFilterOperator.java  |  2 +-
 .../operator/filter/AndFilterOperatorTest.java     |  2 +-
 .../core/operator/filter/OrFilterOperatorTest.java |  4 +-
 .../core/operator/filter/TestFilterOperator.java   |  4 +-
 31 files changed, 124 insertions(+), 183 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 3d3cf0ebab7..9fdebcb87df 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
@@ -34,6 +34,9 @@ import org.roaringbitmap.buffer.MutableRoaringBitmap;
 
 /// The `BlockDocIdSet` contains the matching document ids returned by the
 /// [org.apache.pinot.core.operator.blocks.FilterBlock].
+///
+/// A result known to be empty is represented as an [EmptyDocIdSet], so that a 
parent can recognize it by type and
+/// short-circuit. The index-based implementations offer a `create` factory 
that returns one for an empty input.
 public interface BlockDocIdSet {
 
   /// Returns an iterator of the matching document ids. The document ids 
returned from the iterator should be in
@@ -44,14 +47,6 @@ public interface BlockDocIdSet {
   /// filtering phase. This method should be called after the filtering is 
done.
   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();
@@ -65,19 +60,19 @@ public interface BlockDocIdSet {
       while ((docId = docIdIterator.next()) != Constants.EOF) {
         bitmapWriter.add(docId);
       }
-      return new RangelessBitmapDocIdSet(bitmapWriter.get());
+      return RangelessBitmapDocIdSet.create(bitmapWriter.get());
     }
 
     // NOTE: AND and OR DocIdSet might return BitmapBasedDocIdIterator after 
processing the iterators. Create a new
     //       DocIdSet to prevent processing the iterators again
     if (docIdIterator instanceof RangelessBitmapDocIdIterator) {
-      return new RangelessBitmapDocIdSet((RangelessBitmapDocIdIterator) 
docIdIterator);
+      return RangelessBitmapDocIdSet.create((RangelessBitmapDocIdIterator) 
docIdIterator);
     }
     if (docIdIterator instanceof BitmapDocIdIterator) {
-      return new BitmapDocIdSet((BitmapDocIdIterator) docIdIterator);
+      return BitmapDocIdSet.create((BitmapDocIdIterator) docIdIterator);
     }
     if (docIdIterator instanceof EmptyDocIdIterator) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
 
     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 7fcde29cc2c..27db4f64709 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
@@ -195,9 +195,4 @@ 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 24b8b8d5034..b70e756f8b0 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,17 +24,38 @@ import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
 
 
 public class BitmapDocIdSet implements BlockDocIdSet {
-  private final ImmutableRoaringBitmap _bitmap;
   private final BitmapDocIdIterator _iterator;
+  private final long _numEntriesScannedInFilter;
+
+  /// Returns a doc id set over the given documents, or [EmptyDocIdSet] when 
there is none.
+  public static BlockDocIdSet create(ImmutableRoaringBitmap docIds, int 
numDocs) {
+    return docIds.isEmpty() ? EmptyDocIdSet.unscanned() : new 
BitmapDocIdSet(docIds, numDocs);
+  }
+
+  /// Returns a doc id set over the given documents found by scanning 
`numEntriesScannedInFilter` entries, or
+  /// [EmptyDocIdSet] when there is none.
+  public static BlockDocIdSet create(ImmutableRoaringBitmap docIds, int 
numDocs, long numEntriesScannedInFilter) {
+    return docIds.isEmpty() ? new EmptyDocIdSet(numEntriesScannedInFilter)
+        : new BitmapDocIdSet(docIds, numDocs, numEntriesScannedInFilter);
+  }
+
+  /// Returns a doc id set over the documents of the given iterator, or 
[EmptyDocIdSet] when there is none.
+  public static BlockDocIdSet create(BitmapDocIdIterator iterator) {
+    return iterator.getDocIds().isEmpty() ? EmptyDocIdSet.unscanned() : new 
BitmapDocIdSet(iterator);
+  }
 
   public BitmapDocIdSet(ImmutableRoaringBitmap docIds, int numDocs) {
-    _bitmap = docIds;
+    this(docIds, numDocs, 0L);
+  }
+
+  public BitmapDocIdSet(ImmutableRoaringBitmap docIds, int numDocs, long 
numEntriesScannedInFilter) {
     _iterator = new BitmapDocIdIterator(docIds, numDocs);
+    _numEntriesScannedInFilter = numEntriesScannedInFilter;
   }
 
   public BitmapDocIdSet(BitmapDocIdIterator iterator) {
-    _bitmap = null;
     _iterator = iterator;
+    _numEntriesScannedInFilter = 0L;
   }
 
   @Override
@@ -44,14 +65,6 @@ public class BitmapDocIdSet implements BlockDocIdSet {
 
   @Override
   public long getNumEntriesScannedInFilter() {
-    return 0L;
-  }
-
-  @Override
-  public BlockDocIdSet getOptimizedDocIdSet() {
-    if (_bitmap != null && _bitmap.isEmpty()) {
-      return EmptyDocIdSet.getInstance();
-    }
-    return this;
+    return _numEntriesScannedInFilter;
   }
 }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/EmptyDocIdSet.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/EmptyDocIdSet.java
index aacba8be0a3..ea08723cd8d 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/EmptyDocIdSet.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/EmptyDocIdSet.java
@@ -22,15 +22,22 @@ import org.apache.pinot.core.common.BlockDocIdSet;
 import org.apache.pinot.core.operator.dociditerators.EmptyDocIdIterator;
 
 
-/// Singleton class which extends [BlockDocIdSet] that is empty, i.e. does not 
contain any document.
+/// A [BlockDocIdSet] that does not contain any document.
+///
+/// It keeps the number of entries scanned in the filter before the result was 
found to be empty, so that the execution
+/// stats still account for that work. A result found without scanning uses 
the shared instance from [#unscanned].
 public final class EmptyDocIdSet implements BlockDocIdSet {
-  private EmptyDocIdSet() {
+  private static final EmptyDocIdSet UNSCANNED = new EmptyDocIdSet(0L);
+
+  /// Returns the shared instance for an empty result found without scanning.
+  public static EmptyDocIdSet unscanned() {
+    return UNSCANNED;
   }
 
-  private static final EmptyDocIdSet INSTANCE = new EmptyDocIdSet();
+  private final long _numEntriesScannedInFilter;
 
-  public static EmptyDocIdSet getInstance() {
-    return INSTANCE;
+  public EmptyDocIdSet(long numEntriesScannedInFilter) {
+    _numEntriesScannedInFilter = numEntriesScannedInFilter;
   }
 
   @Override
@@ -40,6 +47,6 @@ public final class EmptyDocIdSet implements BlockDocIdSet {
 
   @Override
   public long getNumEntriesScannedInFilter() {
-    return 0L;
+    return _numEntriesScannedInFilter;
   }
 }
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 cb5630b7db8..2705a6d4e28 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
@@ -132,9 +132,4 @@ 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 3f8932c3325..3ff786f5e9d 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
@@ -26,6 +26,16 @@ import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
 public class RangelessBitmapDocIdSet implements BlockDocIdSet {
   private final RangelessBitmapDocIdIterator _iterator;
 
+  /// Returns a doc id set over the given documents, or [EmptyDocIdSet] when 
there is none.
+  public static BlockDocIdSet create(ImmutableRoaringBitmap docIds) {
+    return docIds.isEmpty() ? EmptyDocIdSet.unscanned() : new 
RangelessBitmapDocIdSet(docIds);
+  }
+
+  /// Returns a doc id set over the documents of the given iterator, or 
[EmptyDocIdSet] when there is none.
+  public static BlockDocIdSet create(RangelessBitmapDocIdIterator iterator) {
+    return iterator.getDocIds().isEmpty() ? EmptyDocIdSet.unscanned() : new 
RangelessBitmapDocIdSet(iterator);
+  }
+
   public RangelessBitmapDocIdSet(ImmutableRoaringBitmap docIds) {
     this(new RangelessBitmapDocIdIterator(docIds));
   }
@@ -43,12 +53,4 @@ 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/ShortCircuitingDocIdSet.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/ShortCircuitingDocIdSet.java
deleted file mode 100644
index ff7bed2d699..00000000000
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/docidsets/ShortCircuitingDocIdSet.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * 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.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.EmptyDocIdIterator;
-
-
-/// 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 ShortCircuitingDocIdSet(long numEntriesScannedInFilter) {
-    _numEntriesScannedInFilter = numEntriesScannedInFilter;
-  }
-
-  @Override
-  public BlockDocIdIterator iterator() {
-    return EmptyDocIdIterator.getInstance();
-  }
-
-  @Override
-  public long getNumEntriesScannedInFilter() {
-    return _numEntriesScannedInFilter;
-  }
-
-  @Override
-  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 ad39d6dc643..23c1cbc6dfd 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
@@ -27,6 +27,11 @@ import org.apache.pinot.spi.utils.Pairs.IntPair;
 public final class SortedDocIdSet implements BlockDocIdSet {
   private final List<IntPair> _docIdRanges;
 
+  /// Returns a doc id set over the given document id ranges, or 
[EmptyDocIdSet] when there is none.
+  public static BlockDocIdSet create(List<IntPair> docIdRanges) {
+    return docIdRanges.isEmpty() ? EmptyDocIdSet.unscanned() : new 
SortedDocIdSet(docIdRanges);
+  }
+
   // NOTE: No need to track numDocs because sorted index can only apply to 
ImmutableSegment, so the document ids are
   //       always smaller than numDocs.
   public SortedDocIdSet(List<IntPair> docIdRanges) {
@@ -42,12 +47,4 @@ 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 fca2858a5ed..3ea299d8a48 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
@@ -28,7 +28,6 @@ import org.apache.pinot.core.common.Operator;
 import org.apache.pinot.core.operator.docidsets.AndDocIdSet;
 import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
 import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
-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;
@@ -55,15 +54,14 @@ public class AndFilterOperator extends BaseFilterOperator {
     long totalEntriesScanned = 0L;
     for (BaseFilterOperator filterOperator : _filterOperators) {
       BlockDocIdSet blockDocIdSet = filterOperator.getTrues();
-      BlockDocIdSet optimizedDocIdSet = blockDocIdSet.getOptimizedDocIdSet();
       totalEntriesScanned += blockDocIdSet.getNumEntriesScannedInFilter();
-      if (optimizedDocIdSet instanceof EmptyDocIdSet) {
-        return new ShortCircuitingDocIdSet(totalEntriesScanned);
+      if (blockDocIdSet instanceof EmptyDocIdSet) {
+        return new EmptyDocIdSet(totalEntriesScanned);
       }
-      if (optimizedDocIdSet instanceof MatchAllDocIdSet) {
+      if (blockDocIdSet instanceof MatchAllDocIdSet) {
         continue;
       }
-      blockDocIdSets.add(optimizedDocIdSet);
+      blockDocIdSets.add(blockDocIdSet);
     }
     if (blockDocIdSets.isEmpty()) {
       return new MatchAllDocIdSet(_numDocs);
@@ -78,7 +76,7 @@ public class AndFilterOperator extends BaseFilterOperator {
     for (BaseFilterOperator filterOperator : _filterOperators) {
       BlockDocIdSet childNotFalses = filterOperator.getNotFalses();
       if (childNotFalses instanceof EmptyDocIdSet) {
-        return EmptyDocIdSet.getInstance();
+        return EmptyDocIdSet.unscanned();
       }
       if (childNotFalses instanceof MatchAllDocIdSet) {
         continue;
@@ -93,7 +91,7 @@ public class AndFilterOperator extends BaseFilterOperator {
 
   @Override
   protected BlockDocIdSet getNulls() {
-    return mayHaveNulls() ? deriveNulls(_queryOptions) : 
EmptyDocIdSet.getInstance();
+    return mayHaveNulls() ? deriveNulls(_queryOptions) : 
EmptyDocIdSet.unscanned();
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseColumnFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseColumnFilterOperator.java
index e74da0edb5c..d20f087bd43 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseColumnFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseColumnFilterOperator.java
@@ -55,7 +55,7 @@ public abstract class BaseColumnFilterOperator extends 
BaseFilterOperator {
 
   @Override
   protected BlockDocIdSet getNulls() {
-    return _nullBitmap != null ? new BitmapDocIdSet(_nullBitmap, _numDocs) : 
EmptyDocIdSet.getInstance();
+    return _nullBitmap != null ? new BitmapDocIdSet(_nullBitmap, _numDocs) : 
EmptyDocIdSet.unscanned();
   }
 
   /// The not-false documents are the ones matching the predicate over the 
stored values together with the null ones.
@@ -66,6 +66,9 @@ public abstract class BaseColumnFilterOperator extends 
BaseFilterOperator {
     if (_nullBitmap == null) {
       return matches;
     }
+    if (matches instanceof EmptyDocIdSet) {
+      return new BitmapDocIdSet(_nullBitmap, _numDocs, 
matches.getNumEntriesScannedInFilter());
+    }
     return new OrDocIdSet(List.of(matches, new BitmapDocIdSet(_nullBitmap, 
_numDocs)), _numDocs);
   }
 
@@ -96,6 +99,9 @@ public abstract class BaseColumnFilterOperator extends 
BaseFilterOperator {
   }
 
   private BlockDocIdSet excludeNulls(BlockDocIdSet blockDocIdSet, 
ImmutableRoaringBitmap nullBitmap) {
+    if (blockDocIdSet instanceof EmptyDocIdSet) {
+      return blockDocIdSet;
+    }
     return new AndDocIdSet(List.of(blockDocIdSet,
         new BitmapDocIdSet(ImmutableRoaringBitmap.flip(nullBitmap, 0, (long) 
_numDocs), _numDocs)),
         _queryContext.getQueryOptions());
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseFilterOperator.java
index 0293a003d9a..5ef8d1f1ca0 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BaseFilterOperator.java
@@ -147,7 +147,7 @@ public abstract class BaseFilterOperator extends 
BaseOperator<FilterBlock> {
 
   /// @return document IDs in which the predicate evaluates to NULL.
   protected BlockDocIdSet getNulls() {
-    return EmptyDocIdSet.getInstance();
+    return EmptyDocIdSet.unscanned();
   }
 
   /// Returns the document IDs in which the predicate does not evaluate to 
false: the true ones and, with null
@@ -171,13 +171,13 @@ public abstract class BaseFilterOperator extends 
BaseOperator<FilterBlock> {
   /// Only for operators that override [#getNotFalses]. The default 
[#getNotFalses] reads [#getNulls], so an operator
   /// that keeps it would recurse; a leaf returns its UNKNOWN documents 
directly instead.
   protected BlockDocIdSet deriveNulls(@Nullable Map<String, String> 
queryOptions) {
-    BlockDocIdSet notFalses = getNotFalses().getOptimizedDocIdSet();
+    BlockDocIdSet notFalses = getNotFalses();
     if (notFalses instanceof EmptyDocIdSet) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
-    BlockDocIdSet trues = getTrues().getOptimizedDocIdSet();
+    BlockDocIdSet trues = getTrues();
     if (trues instanceof MatchAllDocIdSet) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     if (trues instanceof EmptyDocIdSet) {
       return notFalses;
@@ -191,7 +191,7 @@ public abstract class BaseFilterOperator extends 
BaseOperator<FilterBlock> {
   protected BlockDocIdSet getFalses() {
     BlockDocIdSet notFalses = getNotFalses();
     if (notFalses instanceof MatchAllDocIdSet) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     if (notFalses instanceof EmptyDocIdSet) {
       return new MatchAllDocIdSet(_numDocs);
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
index 3fbcf1f5944..5fadd719cef 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
@@ -72,15 +72,15 @@ public class BitmapBasedFilterOperator extends 
BaseFilterOperator {
   @Override
   protected BlockDocIdSet getTrues() {
     if (_exclusive) {
-      return new BitmapDocIdSet(ImmutableRoaringBitmap.flip(_docIds, 0L, 
_numDocs), _numDocs);
+      return BitmapDocIdSet.create(ImmutableRoaringBitmap.flip(_docIds, 0L, 
_numDocs), _numDocs);
     } else {
-      return new BitmapDocIdSet(_docIds, _numDocs);
+      return BitmapDocIdSet.create(_docIds, _numDocs);
     }
   }
 
   @Override
   protected BlockDocIdSet getNulls() {
-    return _nullBitmap != null ? new BitmapDocIdSet(_nullBitmap, _numDocs) : 
EmptyDocIdSet.getInstance();
+    return _nullBitmap != null ? new BitmapDocIdSet(_nullBitmap, _numDocs) : 
EmptyDocIdSet.unscanned();
   }
 
   @Override
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 e1a34ad5cec..52800c141aa 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
@@ -61,11 +61,10 @@ 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();
+    if (mainFilterDocIdSet instanceof EmptyDocIdSet) {
+      return EmptyDocIdSet.unscanned();
     }
     BlockDocIdSet subFilterDocIdSet = 
_subFilterOperator.nextBlock().getBlockDocIdSet();
-    return new AndDocIdSet(Arrays.asList(optimizedMainFilterDocIdSet, 
subFilterDocIdSet), _queryOptions);
+    return new AndDocIdSet(Arrays.asList(mainFilterDocIdSet, 
subFilterDocIdSet), _queryOptions);
   }
 }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/EmptyFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/EmptyFilterOperator.java
index f169549b557..5f2e8ac4bd8 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/EmptyFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/EmptyFilterOperator.java
@@ -58,7 +58,7 @@ public final class EmptyFilterOperator extends 
BaseFilterOperator {
 
   @Override
   protected BlockDocIdSet getTrues() {
-    return EmptyDocIdSet.getInstance();
+    return EmptyDocIdSet.unscanned();
   }
 
 
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java
index 958e72a7287..e11fe8b5d1c 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java
@@ -107,7 +107,7 @@ public class ExactVectorScanFilterOperator extends 
BaseFilterOperator {
     if (_matches == null) {
       _matches = computeExactTopK();
     }
-    return new BitmapDocIdSet(_matches, _numDocs);
+    return BitmapDocIdSet.create(_matches, _numDocs);
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExpressionFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExpressionFilterOperator.java
index 91715f99080..4c00041c4ce 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExpressionFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExpressionFilterOperator.java
@@ -95,7 +95,7 @@ public class ExpressionFilterOperator extends 
BaseFilterOperator {
   /// predicate is UNKNOWN where the expression is null.
   @Override
   protected BlockDocIdSet getNulls() {
-    return isNullCheck() ? EmptyDocIdSet.getInstance() : getExpressionNulls();
+    return isNullCheck() ? EmptyDocIdSet.unscanned() : getExpressionNulls();
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
index 15d7f26610c..c44b6436a9d 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
@@ -132,12 +132,7 @@ public class H3InclusionIndexFilterOperator extends 
BaseFilterOperator {
     ScanBasedDocIdIterator docIdIterator = (ScanBasedDocIdIterator) 
expressionFilterOperator.getTrues().iterator();
     MutableRoaringBitmap result = docIdIterator.applyAnd(partialMatchDocIds);
     result.or(fullMatchDocIds);
-    return new BitmapDocIdSet(result, _numDocs) {
-      @Override
-      public long getNumEntriesScannedInFilter() {
-        return docIdIterator.getNumEntriesScanned();
-      }
-    };
+    return BitmapDocIdSet.create(result, _numDocs, 
docIdIterator.getNumEntriesScanned());
   }
 
   /// Returns the null document IDs for the indexed column when query null 
handling is enabled and the column has a
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
index e9d20aa49c3..ae5510ced67 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
@@ -99,7 +99,7 @@ public class H3IndexFilterOperator extends BaseFilterOperator 
{
   protected BlockDocIdSet getTrues() {
     if (_upperBound < 0 || _lowerBound > _upperBound) {
       // Invalid upper bound, return an empty block
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
 
     try {
@@ -116,7 +116,7 @@ public class H3IndexFilterOperator extends 
BaseFilterOperator {
           MutableRoaringBitmap matchAllDocIds = new MutableRoaringBitmap();
           matchAllDocIds.add(0L, _numDocs);
           matchAllDocIds.andNot(nullDocIds);
-          return new BitmapDocIdSet(matchAllDocIds, _numDocs);
+          return BitmapDocIdSet.create(matchAllDocIds, _numDocs);
         }
 
         // Upper bound only
@@ -246,12 +246,7 @@ public class H3IndexFilterOperator extends 
BaseFilterOperator {
         (ScanBasedDocIdIterator) 
expressionFilterOperator.getTrues().iterator();
     MutableRoaringBitmap result = docIdIterator.applyAnd(partialMatchDocIds);
     result.or(fullMatchDocIds);
-    return new BitmapDocIdSet(result, _numDocs) {
-      @Override
-      public long getNumEntriesScannedInFilter() {
-        return docIdIterator.getNumEntriesScanned();
-      }
-    };
+    return BitmapDocIdSet.create(result, _numDocs, 
docIdIterator.getNumEntriesScanned());
   }
 
   /// Returns the null document IDs for the indexed column when query null 
handling is enabled and the column has a
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/InvertedIndexFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/InvertedIndexFilterOperator.java
index af9d817b447..f4555a0b408 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/InvertedIndexFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/InvertedIndexFilterOperator.java
@@ -62,7 +62,7 @@ public class InvertedIndexFilterOperator extends 
BaseColumnFilterOperator {
     int[] dictIds = _exclusive ? _predicateEvaluator.getNonMatchingDictIds() : 
_predicateEvaluator.getMatchingDictIds();
     int numDictIds = dictIds.length;
     if (numDictIds == 0) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     if (numDictIds == 1) {
       ImmutableRoaringBitmap docIds = 
_invertedIndexReader.getDocIds(dictIds[0]);
@@ -70,12 +70,12 @@ public class InvertedIndexFilterOperator extends 
BaseColumnFilterOperator {
         if (docIds instanceof MutableRoaringBitmap) {
           MutableRoaringBitmap mutableRoaringBitmap = (MutableRoaringBitmap) 
docIds;
           mutableRoaringBitmap.flip(0L, _numDocs);
-          return new BitmapDocIdSet(mutableRoaringBitmap, _numDocs);
+          return BitmapDocIdSet.create(mutableRoaringBitmap, _numDocs);
         } else {
-          return new BitmapDocIdSet(ImmutableRoaringBitmap.flip(docIds, 0L, 
_numDocs), _numDocs);
+          return BitmapDocIdSet.create(ImmutableRoaringBitmap.flip(docIds, 0L, 
_numDocs), _numDocs);
         }
       } else {
-        return new BitmapDocIdSet(docIds, _numDocs);
+        return BitmapDocIdSet.create(docIds, _numDocs);
       }
     } else {
       ImmutableRoaringBitmap[] bitmaps = new 
ImmutableRoaringBitmap[numDictIds];
@@ -92,7 +92,7 @@ public class InvertedIndexFilterOperator extends 
BaseColumnFilterOperator {
         recording.setNumDocsMatchingAfterFilter(docIds.getCardinality());
         recording.setFilter(FilterType.INDEX, 
String.valueOf(_predicateEvaluator.getPredicateType()));
       }
-      return new BitmapDocIdSet(docIds, _numDocs);
+      return BitmapDocIdSet.create(docIds, _numDocs);
     }
   }
 
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JsonMatchFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JsonMatchFilterOperator.java
index 1feae3ae6cc..207542f6f70 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JsonMatchFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JsonMatchFilterOperator.java
@@ -61,7 +61,7 @@ public class JsonMatchFilterOperator extends 
BaseFilterOperator {
   protected BlockDocIdSet getTrues() {
     ImmutableRoaringBitmap bitmap = getMatchingDocIdBitmap();
     record(bitmap);
-    return new BitmapDocIdSet(bitmap, _numDocs);
+    return BitmapDocIdSet.create(bitmap, _numDocs);
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/NotFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/NotFilterOperator.java
index 56037a91e5a..73a73826479 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/NotFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/NotFilterOperator.java
@@ -74,7 +74,7 @@ public class NotFilterOperator extends BaseFilterOperator {
   protected BlockDocIdSet getNotFalses() {
     BlockDocIdSet childTrues = _filterOperator.getTrues();
     if (childTrues instanceof MatchAllDocIdSet) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     if (childTrues instanceof EmptyDocIdSet) {
       return new MatchAllDocIdSet(_numDocs);
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 ed1d0ac75e1..d19b3953392 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
@@ -27,7 +27,6 @@ import org.apache.pinot.core.common.Operator;
 import org.apache.pinot.core.operator.docidsets.EmptyDocIdSet;
 import org.apache.pinot.core.operator.docidsets.MatchAllDocIdSet;
 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;
@@ -54,18 +53,17 @@ public class OrFilterOperator extends BaseFilterOperator {
     long totalEntriesScanned = 0L;
     for (BaseFilterOperator filterOperator : _filterOperators) {
       BlockDocIdSet blockDocIdSet = filterOperator.getTrues();
-      BlockDocIdSet optimizedDocIdSet = blockDocIdSet.getOptimizedDocIdSet();
       totalEntriesScanned += blockDocIdSet.getNumEntriesScannedInFilter();
-      if (optimizedDocIdSet instanceof MatchAllDocIdSet) {
+      if (blockDocIdSet instanceof MatchAllDocIdSet) {
         return new MatchAllDocIdSet(_numDocs);
       }
-      if (optimizedDocIdSet instanceof EmptyDocIdSet) {
+      if (blockDocIdSet instanceof EmptyDocIdSet) {
         continue;
       }
-      blockDocIdSets.add(optimizedDocIdSet);
+      blockDocIdSets.add(blockDocIdSet);
     }
     if (blockDocIdSets.isEmpty()) {
-      return new ShortCircuitingDocIdSet(totalEntriesScanned);
+      return new EmptyDocIdSet(totalEntriesScanned);
     }
     return new OrDocIdSet(blockDocIdSets, _numDocs);
   }
@@ -85,14 +83,14 @@ public class OrFilterOperator extends BaseFilterOperator {
       notFalses.add(childNotFalses);
     }
     if (notFalses.isEmpty()) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     return notFalses.size() == 1 ? notFalses.get(0) : new 
OrDocIdSet(notFalses, _numDocs);
   }
 
   @Override
   protected BlockDocIdSet getNulls() {
-    return mayHaveNulls() ? deriveNulls(_queryOptions) : 
EmptyDocIdSet.getInstance();
+    return mayHaveNulls() ? deriveNulls(_queryOptions) : 
EmptyDocIdSet.unscanned();
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/RangeIndexBasedFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/RangeIndexBasedFilterOperator.java
index 4dda6267e9b..5e3d7884e57 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/RangeIndexBasedFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/RangeIndexBasedFilterOperator.java
@@ -26,6 +26,7 @@ import org.apache.pinot.core.common.Operator;
 import org.apache.pinot.core.operator.ExplainAttributeBuilder;
 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.filter.predicate.PredicateEvaluator;
 import org.apache.pinot.core.operator.filter.predicate.traits.DoubleRange;
 import org.apache.pinot.core.operator.filter.predicate.traits.DoubleValue;
@@ -85,7 +86,7 @@ public class RangeIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
     if (_rangeIndexReader.isExact()) {
       ImmutableRoaringBitmap matches = getMatchingDocIds();
       recordFilter(matches);
-      return new BitmapDocIdSet(matches, _numDocs);
+      return BitmapDocIdSet.create(matches, _numDocs);
     }
     return evaluateLegacyRangeFilter();
   }
@@ -98,7 +99,7 @@ public class RangeIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
     ImmutableRoaringBitmap partialMatches = getPartiallyMatchingDocIds();
     // this branch is likely until RangeIndexReader reimplemented and enabled 
by default
     if (partialMatches == null) {
-      return new BitmapDocIdSet(matches == null ? new MutableRoaringBitmap() : 
matches, _numDocs);
+      return matches != null ? BitmapDocIdSet.create(matches, _numDocs) : 
EmptyDocIdSet.unscanned();
     }
     // Need to scan the first and last range as they might be partially matched
     ScanBasedFilterOperator scanBasedFilterOperator =
@@ -109,13 +110,7 @@ public class RangeIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
       docIds.or(matches);
     }
     recordFilter(matches);
-    return new BitmapDocIdSet(docIds, _numDocs) {
-      // Override this method to reflect the entries scanned
-      @Override
-      public long getNumEntriesScannedInFilter() {
-        return scanBasedDocIdSet.getNumEntriesScannedInFilter();
-      }
-    };
+    return BitmapDocIdSet.create(docIds, _numDocs, 
scanBasedDocIdSet.getNumEntriesScannedInFilter());
   }
 
   ImmutableRoaringBitmap getMatchingDocIds() {
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/SortedIndexBasedFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/SortedIndexBasedFilterOperator.java
index 8ecaa207647..2765d716053 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/SortedIndexBasedFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/SortedIndexBasedFilterOperator.java
@@ -66,7 +66,7 @@ public class SortedIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
       int startDocId = 
_sortedIndexReader.getDocIds(rangePredicateEvaluator.getStartDictId()).getLeft();
       // NOTE: End dictionary id is exclusive in 
OfflineDictionaryBasedRangePredicateEvaluator.
       int endDocId = 
_sortedIndexReader.getDocIds(rangePredicateEvaluator.getEndDictId() - 
1).getRight();
-      return new SortedDocIdSet(List.of(new IntPair(startDocId, endDocId)));
+      return SortedDocIdSet.create(List.of(new IntPair(startDocId, endDocId)));
     } else {
       boolean exclusive = _predicateEvaluator.isExclusive();
       int[] dictIds =
@@ -87,9 +87,9 @@ public class SortedIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
           if (lastDocId < _numDocs - 1) {
             docIdRanges.add(new IntPair(lastDocId + 1, _numDocs - 1));
           }
-          return new SortedDocIdSet(docIdRanges);
+          return SortedDocIdSet.create(docIdRanges);
         } else {
-          return new SortedDocIdSet(List.of(docIdRange));
+          return SortedDocIdSet.create(List.of(docIdRange));
         }
       } else {
         // Merge adjacent docIdRanges (dictIds are already sorted)
@@ -127,7 +127,7 @@ public class SortedIndexBasedFilterOperator extends 
BaseColumnFilterOperator {
           docIdRanges = invertedDocIdRanges;
         }
 
-        return new SortedDocIdSet(docIdRanges);
+        return SortedDocIdSet.create(docIdRanges);
       }
     }
   }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TextMatchFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TextMatchFilterOperator.java
index a993be1421e..793fcfedb2d 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TextMatchFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TextMatchFilterOperator.java
@@ -63,11 +63,12 @@ public class TextMatchFilterOperator extends 
BaseFilterOperator {
   @Override
   protected BlockDocIdSet getTrues() {
     if (_textIndexReader.isMultiColumn()) {
-      return new BitmapDocIdSet(
+      return BitmapDocIdSet.create(
           ((MultiColumnTextIndexReader) _textIndexReader).getDocIds(_column, 
_predicate.getValue(),
               _predicate.getOptions()), _numDocs);
     } else {
-      return new 
BitmapDocIdSet(_textIndexReader.getDocIds(_predicate.getValue(), 
_predicate.getOptions()), _numDocs);
+      return 
BitmapDocIdSet.create(_textIndexReader.getDocIds(_predicate.getValue(), 
_predicate.getOptions()),
+          _numDocs);
     }
   }
 
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorRadiusFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorRadiusFilterOperator.java
index f3dfabf3514..8aa0482edc7 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorRadiusFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorRadiusFilterOperator.java
@@ -104,7 +104,7 @@ public class VectorRadiusFilterOperator extends 
BaseFilterOperator {
     if (_matches == null) {
       _matches = executeSearch();
     }
-    return new BitmapDocIdSet(_matches, _numDocs);
+    return BitmapDocIdSet.create(_matches, _numDocs);
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorSimilarityFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorSimilarityFilterOperator.java
index 1b850c80641..07f12a1bccc 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorSimilarityFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorSimilarityFilterOperator.java
@@ -225,7 +225,7 @@ public class VectorSimilarityFilterOperator extends 
BaseFilterOperator {
     if (_matches == null) {
       _matches = executeSearch();
     }
-    return new BitmapDocIdSet(_matches, _numDocs);
+    return BitmapDocIdSet.create(_matches, _numDocs);
   }
 
   @Override
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/startree/operator/StarTreeFilterOperator.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/startree/operator/StarTreeFilterOperator.java
index 7b9693d88c3..e86b90fd86c 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/startree/operator/StarTreeFilterOperator.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/startree/operator/StarTreeFilterOperator.java
@@ -112,7 +112,7 @@ public class StarTreeFilterOperator extends 
BaseFilterOperator {
   @Override
   protected BlockDocIdSet getTrues() {
     if (_resultEmpty) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     return getFilterOperator().nextBlock().getBlockDocIdSet();
   }
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 5a975d64664..e49ff53c612 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
@@ -250,7 +250,7 @@ public class AndFilterOperatorTest {
             new TestFilterOperator(emptyDocIds, numDocs)
         ), null, numDocs, false);
 
-    assertEquals((andFilterOperator.getTrues()).getOptimizedDocIdSet(), 
EmptyDocIdSet.getInstance());
+    assertTrue(andFilterOperator.getTrues() instanceof EmptyDocIdSet);
   }
 
   @Test
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 4a98c60e616..dae512b450e 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
@@ -199,7 +199,7 @@ public class OrFilterOperatorTest {
             new MatchAllFilterOperator(numDocs)
         ), null, numDocs, false);
 
-    assertTrue((orFilterOperator.getTrues()).getOptimizedDocIdSet() instanceof 
MatchAllDocIdSet);
+    assertTrue(orFilterOperator.getTrues() instanceof MatchAllDocIdSet);
   }
 
   @Test
@@ -213,7 +213,7 @@ public class OrFilterOperatorTest {
             new TestFilterOperator(emptyDocIds, numDocs)
         ), null, numDocs, false);
 
-    assertTrue(orFilterOperator.getTrues().getOptimizedDocIdSet() instanceof 
EmptyDocIdSet);
+    assertTrue(orFilterOperator.getTrues() instanceof EmptyDocIdSet);
   }
 
   @Test
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
similarity index 97%
rename from 
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
rename to 
pinot-core/src/test/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
index a662c77b86a..bb85a574a3a 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
+++ 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/TestFilterOperator.java
@@ -61,7 +61,7 @@ public class TestFilterOperator extends BaseFilterOperator {
       return new MatchAllDocIdSet(_numDocs);
     }
     if (_trueDocIds.length == 0) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     return new TestBlockDocIdSet(_trueDocIds);
   }
@@ -69,7 +69,7 @@ public class TestFilterOperator extends BaseFilterOperator {
   @Override
   protected BlockDocIdSet getNulls() {
     if (_nullDocIds.length == 0) {
-      return EmptyDocIdSet.getInstance();
+      return EmptyDocIdSet.unscanned();
     }
     return new TestBlockDocIdSet(_nullDocIds);
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to