xiangfu0 opened a new pull request, #19464:
URL: https://github.com/apache/pinot/pull/19464

   ## Problem
   
   `FilterAwareVectorIndexReader` requires a non-null pre-filter bitmap, but 
its five implementations enforced that
   four different ways:
   
   | Reader | Before |
   |---|---|
   | `MutableVectorIndex` | `checkNotNull` → NPE with contract message |
   | `HnswVectorIndexReader` | **no guard** — NPE from `BaseFilterQuery`'s 
iterator |
   | `IvfFlatVectorIndexReader` | **no guard** — NPE on 
`preFilterBitmap.isEmpty()` |
   | `IvfPqVectorIndexReader` | **no guard** — NPE on 
`preFilterBitmap.isEmpty()` |
   | `IvfOnDiskVectorIndexReader` | `checkArgument` → IAE, different message |
   
   A caller that lost its filter got a different failure purely based on which 
backend indexed the column. In three
   cases it was an unmessaged NPE raised from inside Lucene's traversal:
   
   ```
   Cannot invoke "ImmutableRoaringBitmap.getLongCardinality()" because 
"this.this$0._docIds" is null
   ```
   
   The sole production caller (`VectorSimilarityFilterOperator`) null-checks 
before dispatching, so this is a
   robustness and diagnosability fix rather than a live bug.
   
   ## Change
   
   - State the failure mode once on the SPI method, including that an empty 
bitmap admits nothing. Comment-only.
   - Guard `IvfFlat` and `IvfPq`; align `IvfOnDisk` on the same exception type 
and message.
   - Short-circuit an empty bitmap in HNSW before building the query — its 
filter clause would otherwise walk every
     doc in every leaf, translating ids and testing membership, to assemble an 
accept set that admits nothing.
   - Report `supportsPreFilter()` in HNSW and `IvfOnDisk` debug info instead of 
a hardcoded literal.
   
   ## Tests
   
   Every reader now has a null-contract test. Two tests are restored from 
#19303, which dropped them before merge:
   the mutable null-bitmap rejection, and the IVF_PQ assertion that candidate 
generation honors the pre-filter — it
   asserts up front that the allowed docs sit *outside* the unfiltered top-K, 
so an implementation that intersected
   afterwards would return empty and fail.
   
   Both new guards were mutation-tested rather than assumed:
   
   - Delete the null guard → `testFilteredReaderRejectsNullBitmap` fails with 
the raw `getLongCardinality()` NPE above.
   - Delete the empty short-circuit → 
`testFilteredReaderShortCircuitsEmptyBitmapBeforeBuildingQuery` fails with
     `vectorUseBoundedQueue=false requires vectorEfSearch to be set`, proving 
the short-circuit runs before query
     construction. (An assertion that the result is merely empty does **not** 
discriminate — Lucene returns no hits
     for a zero-match filter anyway.)
   
   77 vector tests pass in `pinot-segment-local`; spotless, checkstyle and 
license are clean.
   
   Follow-up to #19303.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to