Repository navigation
fix(analytics): Fix multi-shard GROUP BY on multi_value keys - #23091
Conversation
PR Code Analyzer ❗AI-powered 'Code-Diff-Analyzer' found issues on commit d7e9e3d. ⛔ Hard block: Issues at Medium severity or above will block this PR from merging.
The table above displays the top 10 most important findings. Pull Requests Author(s): Please update your Pull Request according to the report above. Repository Maintainer(s): You can Thanks. |
PR Reviewer Guide 🔍(Review updated until commit bc83ce6)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to bc83ce6 Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit ae1d4a4
Suggestions up to commit be771bd
Suggestions up to commit f7b202d
Suggestions up to commit d7e9e3d
|
Implicit GROUP BY on a multi_value keyword field failed on any index with more than one shard, in two layers on the coordinator reduce stage. First, attachFragmentOnTop round-trips the shard (PARTIAL) fragment through the stock substrait-java ProtoPlanConverter, which maps the opensearch://analytics/multi_value_expand/v1 ExtensionSingle to an EmptyDetail with an empty record type. The grouping key that the expansion appended was then out of range, failing plan assembly with "Field reference offset (N) must be less than number of fields in struct (0)". MultiValueExpandDetail gains a fromProto inverse and derives its record type from the input (append or replace the LIST column with its nullable element), and decodePlan uses a ProtoPlanConverter whose detailFromExtensionSingleRel recognizes the extension type URL. Second, the FINAL aggregate's StageInputTableScan still carried the pre-expansion LIST type while the shards stream the already-expanded scalar key, so DataFusion rejected the reduce ReadRel with "Field 'tags' in Substrait schema has a different type (List(Utf8)) than the corresponding field in the table schema (Utf8View)". OpenSearchAggregate now tags FINAL-mode aggregates with a RelHint when stripping annotations, and MultiValueRelRewriter retypes LIST group keys on a FINAL aggregate over a stage input to their element type instead of re-expanding them. Unit tests cover the decode round trip and the FINAL retype path; the three MultiValueAggregationIT cases pinned on the issue are un-skipped. Resolves opensearch-project#23057 Signed-off-by: Varun Bansal <bansvaru@amazon.com>
d7e9e3d to
f7b202d
Compare
|
Persistent review updated to latest commit f7b202d |
|
❌ Gradle check result for f7b202d: 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? |
|
Persistent review updated to latest commit be771bd |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #23091 +/- ##
============================================
- Coverage 71.78% 71.78% -0.01%
- Complexity 77773 77792 +19
============================================
Files 6179 6179
Lines 360740 360749 +9
Branches 52506 52507 +1
============================================
- Hits 258971 258960 -11
- Misses 81172 81179 +7
- Partials 20597 20610 +13 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Persistent review updated to latest commit ae1d4a4 |
|
❌ Gradle check result for ae1d4a4: 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? |
|
Persistent review updated to latest commit bc83ce6 |
|
❌ Gradle check result for bc83ce6: 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? |
|
❕ Gradle check result for bc83ce6: UNSTABLE Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure. |
Description
Implicit
GROUP BYon amulti_valuekeyword field (e.g.source = idx | stats count() by tags) failed on any index with more than one shard. Single-shard queries were unaffected because they never build a coordinator reduce fragment. Two layers on the reduce stage were wrong:Plan assembly (400).
attachFragmentOnTopround-trips the shard (PARTIAL) fragment through the stock substrait-javaProtoPlanConverter, which maps theopensearch://analytics/multi_value_expand/v1ExtensionSingleto anEmptyDetailwith an empty record type. The grouping key appended by the expansion was then out of range:Field reference offset (N) must be less than number of fields in struct (0).MultiValueExpandDetailgains afromProtoinverse and derives its record type from the input (append or replace the LIST column with its nullable element), anddecodePlanuses aProtoPlanConverterwhosedetailFromExtensionSingleRelrecognizes the extension type URL.Execution (500). The FINAL aggregate's
StageInputTableScanstill carried the pre-expansion LIST type while the shards stream the already-expanded scalar key, so DataFusion rejected the reduceReadRel:Field 'tags' in Substrait schema has a different type (List(Utf8)) than the corresponding field in the table schema (Utf8View).OpenSearchAggregate.stripAnnotationsnow tags FINAL-mode aggregates with aRelHint, andMultiValueRelRewriterretypes LIST group keys on a FINAL aggregate over a stage input to their element type instead of re-expanding them; PARTIAL aggregates keep the existing expansion path.Tests:
DataFusionFragmentConvertorTestsadds a decode round-trip test (reproduces the offset error on old code) and a FINAL-retype test (no expand extension emitted, key declared as scalar in the ReadRel schema). The threeMultiValueAggregationITcases pinned on #23057 (count() by tags,sum(latency) by tags, region, SQLGROUP BY tags, regionon 2 shards) are un-skipped and pass against the live 2-node cluster.Supersedes #23067 with a minimal backend-only change (no planner refactor).
Related Issues
Resolves #23057
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.