Fix UnsupportedOperationException on nested sort during early termination#22534
Conversation
…tion (opensearch-project#17140, opensearch-project#21537) The nested MultiValueMode.select(...parentDocs, childDocs...) variants returned an AbstractNumericDocValues/AbstractBinaryDocValues/AbstractSortedDocValues that overrode only advanceExact, not advance(int). Since opensearch-project#12089 enabled point-based sort optimization, NumericComparator's competitive iterator calls advance() during early termination (track_total_hits:false), hitting the base UnsupportedOperationException. Implements advance() on all four nested selects that lacked it (long, unsigned-long, binary, sorted/keyword). For the numeric/binary selects advanceExact always returns true (missing-value fallback), so advance(target) positions on target. The sorted select is sparse (no missing-value fallback for ords), so advance() walks the parent bitset to the next parent that has an ord. Adds MultiValueModeTests coverage. Signed-off-by: serhiy-bzhezytskyy <me@serhiy-bzhezytskyy.com>
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
|
❌ Gradle check result for 0b6e88c: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
The gradle-check failure is Could someone re-run gradle-check when convenient? Thanks! |
Description
The nested
MultiValueMode.select(...parentDocs, childDocs...)variants returned a doc-values instance that overrode onlyadvanceExact, notadvance(int). Since #12089 enabled the point-based sort optimization,NumericComparator's competitive iterator callsadvance()during early termination (i.e.track_total_hits: false), which hit the baseAbstractNumericDocValues.advance()and threwUnsupportedOperationException. Withtrack_total_hits: truethere's no early termination, soadvance()isn't called — which is why the failure only appeared without it.This implements
advance()on the nested selects:advanceExactalways returnstrue(a missing value is emitted when no children match), so every parent doc has a value andadvance(target)positions directly ontarget.advanceExactcan returnfalse(no missing-value fallback for ords), so values are sparse;advance()walks the parent bitset to the next parent that has an ord.advance(), but asvalues.advance(target)(advancing the child values iterator). Aligned it to the same parent-positioning semantics as the others, per the discussion on [Bug]: Intermittent UnsupportedOperationException errors with nested queries #17140.Tests added to
MultiValueModeTestscovering the numeric, unsigned-long, and double nested selects. FullMultiValueModeTestsand the sort / comparator-source suites pass locally.Related Issues
Resolves #17140
Resolves #21537
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.