u70b3 commented on code in PR #4971:
URL: https://github.com/apache/datafusion-comet/pull/4971#discussion_r3974967321


##########
native/spark-expr/src/string_funcs/get_json_object.rs:
##########
@@ -320,50 +339,52 @@ struct SegmentVisitor<'a> {
 }
 
 impl<'de> Visitor<'de> for SegmentVisitor<'_> {
-    type Value = Option<Value>;
+    type Value = PathResult;
 
     fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str("a JSON value")
     }
 
     fn visit_bool<E>(self, _: bool) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_i64<E>(self, _: i64) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_u64<E>(self, _: u64) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_f64<E>(self, _: f64) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_str<E>(self, _: &str) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_unit<E>(self) -> Result<Self::Value, E> {
-        Ok(None)
+        Ok(PathResult::default())
     }
 
     fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, 
A::Error> {
         let PathSegment::Field(name) = &self.segments[0] else {
             IgnoredAny.visit_map(map)?;
-            return Ok(None);
+            return Ok(PathResult::default());
         };
 
-        let mut found = None;
-        // Every entry is visited so that a duplicated key resolves to its last
-        // occurrence, as it would in a parsed object.
+        let mut found = PathResult::default();
         while let Some(matched) = map.next_key_seed(KeySeed(name))? {
-            if matched {
-                found = map.next_value_seed(PathSeed {
+            if matched && !found.matched {

Review Comment:
   Good catch — confirmed against Spark 4.1.3, and the root cause was deeper 
than the duplicate-key lock: Spark never treats `[*][*]` as two wildcards. Its 
parser emits `Subscript :: Wildcard :: Subscript :: Wildcard`, and 
`evaluatePath` consumes both at once (the "non-structure preserving double 
wildcard" case in `JsonExpressionEvalUtils`), applying the remaining path to 
the outer array's *elements themselves* in flatten style. So for 
`{"a":[[{"b":1}]],"a":null}` with `$.a[*][*].b`, the first `a`'s outer element 
`[{"b":1}]` is an array and cannot match `.b` — nothing is written, `dirty` 
stays false — and the second `a` is null, hence SQL NULL.
   
   Fixed in the latest commit: `[*][*]` now parses to a dedicated 
`DoubleWildcard` segment. The remaining path is applied to the outer elements 
with Spark's flatten style (array leaves are spliced recursively; an array that 
flattens to nothing writes no leaf nodes, so it is not a match), and the 
collected matches are always wrapped in a single array, even when there is only 
one — matching Spark's generator, which unconditionally wraps this case.
   
   Regression coverage:
   - `test_duplicate_key_double_wildcard_match_decision` covers this exact 
input (`-> NULL`), the same shape without the duplicate key, and the 
fall-through to a later occurrence that does match 
(`{"a":[[{"b":1}]],"a":[{"b":2}]}` -> `[2]`).
   - Five more unit tests pin the flatten semantics (one-level flatten 
mirroring Spark's `$.store.basket[*][*]` suite case, single match staying 
wrapped, empty-flatten no-match, objects under `[*][*].b`, recursive flatten).
   - Added `[*][*]` queries — including this exact query — to 
`spark/src/test/resources/sql-tests/expressions/string/get_json_object.sql`, so 
CI validates against Spark itself. `CometSqlFileTestSuite` passes locally on 
Spark 4.1.3.
   



-- 
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