fix: gracefully handle scalar values under object-typed fields when decoding results (#5685) - #5732
Conversation
PR Reviewer Guide 🔍(Review updated until commit 4d3a6d5)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 4d3a6d5 Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit 3f0f955
Suggestions up to commit 22f7212
Suggestions up to commit 7d340e8
|
7d340e8 to
22f7212
Compare
|
Persistent review updated to latest commit 22f7212 |
| || type == STRUCT) { | ||
| return parseStruct(content, field, supportArrays); | ||
| // A scalar under an object-typed field (wildcard over indices with conflicting mappings) | ||
| // would throw here; return null instead (#5685). CCE-scoped: this is also the whole-document |
There was a problem hiding this comment.
lets just remove the inline PR link - instead if it is necessary lets to the yaml test with issue id.
There was a problem hiding this comment.
Updated to use yaml test as IT
22f7212 to
3f0f955
Compare
|
Persistent review updated to latest commit 3f0f955 |
|
Related to #5610 |
…ch-project#5685) On the Calcite path, `dedup` pushes down as a composite aggregation whose surviving row is fetched via top_hits and decoded from the nested _source. When a wildcard spans indices that disagree on whether a path is an object or a scalar, the merged mapping types the path as an object (STRUCT) while some documents store a scalar there. Decoding that scalar as a struct threw `java.sql.SQLException: ... class java.lang.String cannot be cast to class java.util.Map`, failing the whole query (100% on the reporting customer's `source=logs-pr172502-*`). Guard the STRUCT branch of OpenSearchExprValueFactory.parse to degrade a scalar-under-object value to null, completing the graceful handling opensearch-project#5618 added for the geo_point and scalar branches. The catch is scoped to ClassCastException because this branch is also the whole-document parse entry point and each nested object level is wrapped independently, so a broader catch would swallow legitimate errors raised deeper in the recursion. Adds a factory unit regression and a yamlRestTest (issues/5685.yml) covering the object-vs-scalar conflict and its mirror (scalar-vs-object, guarding opensearch-project#5618). Signed-off-by: Kai Huang <ahkcs@amazon.com>
3f0f955 to
4d3a6d5
Compare
|
Persistent review updated to latest commit 4d3a6d5 |
| Content-Type: 'application/json' | ||
| ppl: | ||
| body: | ||
| query: "source=dedup_conflict_a_5685,dedup_conflict_b_5685 | dedup host | fields host | sort host" |
There was a problem hiding this comment.
Could you confirm is specifying index list in source deterministic to reproduce the issue? Because we have LatestRule which relies on the order and always choose the last one.
There was a problem hiding this comment.
Yes, it's deterministic and does reproduce pre-fix. The determinism isn't from source order — only _b maps resource.attributes.k8s.namespace (as object) while _a (dynamic:false) never maps it, so the merged type is always object with no LatestRule tiebreak. _a's document still holds a scalar there, so decode hits String cannot be cast to Map every run without the fix. wildcard vs explicit list behaves the same.
Description
On the Calcite path, PPL
deduppushes down as a composite aggregation whose surviving row is fetched viatop_hitsand decoded from the nested_source. When a query spans a wildcard/alias over indices that disagree on whether a path is an object or a scalar, the cross-index mapping merge types the path as an object (STRUCT) while some documents store a scalar there. Decoding that scalar as a struct threw and failed the whole query:This guards the STRUCT branch of
OpenSearchExprValueFactory.parseto degrade a scalar-under-object value tonull, completing the graceful handling #5618 added for the geo_point and scalar branches (it did not cover the object/STRUCT branch). The catch is scoped toClassCastException— this branch is also the whole-document parse entry point and each nested object level is wrapped independently, so a broader catch would swallow legitimate errors raised deeper in the recursion.Issues Resolved
Closes #5685
Behavior (before → after)
dedupover wildcard, object-vs-scalar conflict on an object pathString cannot be cast to Mapnulldedupover wildcard, scalar-vs-object conflict (mirror)IllegalStateException(correct)Testing
OpenSearchExprValueFactoryTest.constructStructWithScalarValueReturnsNullrest-api-spec/test/issues/5685.yml— object-vs-scalar conflict and its mirror (scalar-vs-object).OpenSearchExprValueFactoryTestand the:opensearchunit suite pass;integ-testcompiles.Check List
--signoff.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.