cloud-fan commented on code in PR #58831:
URL: https://github.com/apache/spark/pull/58831#discussion_r4407365810


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInsertionBase.scala:
##########
@@ -52,9 +53,9 @@ abstract class ResolveInsertionBase extends Rule[LogicalPlan] 
{
           case (input: StructType, expected: StructType) =>
             // Rename inner fields of the input column to pass the by-name 
INSERT analysis.
             Alias(Cast(queryOutputCol, renameFieldsInStruct(input, expected)), 
resolvedCol.name)()
-          case (input: ArrayType, expected: ArrayType) =>
+          case (input: ArrayType, expected: ArrayType) if 
resolveNestedFieldsByPosition =>

Review Comment:
   **Non-blocking (P2):** With the flag set to `false`, this guard, the one on 
the map case below, and the two in `renameFieldsInType` stop renaming structs 
inside arrays and maps, so those structs match by name again. That is the code 
before SPARK-58816. The merge target renames them positionally with no flag, 
and SPARK-58816 is already on branch-4.3 and branch-4.x. A user who turns the 
flag off to back out only the new unequal-arity behavior also gets back the 
silent wrong-field writes SPARK-58816 fixed. For example, 
`array(named_struct('y', 20, 'x', 10))` into `ARRAY<STRUCT<x, y>>` writes 
`x=10, y=20`, where the merge target writes `x=20, y=10`. The new 
`SQLInsertTestSuite` test pins that result. The same applies to map keys and 
values, and to arrays or maps nested inside a struct column. No flag value 
reproduces the merge-target behavior.
   
   Dropping the flag from the four array and map cases, and keeping it only on 
the arity condition in `renameFieldsInStruct`, would make `false` restore 
exactly the merge-target behavior. The config doc and the flag-off test's array 
and map expectations would change to match.
   
   **Verification:**
   - **Behavior:** With 
spark.sql.insertInto.columnList.nestedFieldsResolveByPosition.enabled=false, an 
equal-arity struct with reordered field names resolves positionally inside an 
array element, inside a map value, and inside an array nested in a struct 
column; for example array(named_struct('y', 20, 'x', 10)) into ARRAY<STRUCT<x, 
y>> writes x=20, y=10.
   - **Compatibility:** With the flag false, unequal-arity structs at top level 
and inside arrays and maps still resolve by name, so named_struct('y', 1, 'x', 
2, 'z', 3) into STRUCT<x, y> with schema evolution writes {x: 2, y: 1, z: 3}, 
and an equal-arity top-level struct keeps its positional result.
   - **Regression:** With the flag true, the positional results for wider, 
narrower, and collection inputs are unchanged.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInsertionBase.scala:
##########
@@ -64,25 +65,27 @@ abstract class ResolveInsertionBase extends 
Rule[LogicalPlan] {
   }
 
   private def renameFieldsInStruct(input: StructType, expected: StructType): 
StructType = {
-    if (input.length == expected.length) {
+    if (input.length == expected.length || resolveNestedFieldsByPosition) {
       val newFields = input.zip(expected).map { case (f1, f2) =>
         f1.copy(name = f2.name, dataType = renameFieldsInType(f1.dataType, 
f2.dataType))
       }
-      StructType(newFields)
+      StructType(newFields ++ input.drop(expected.length))

Review Comment:
   Thanks for tracing both paths. On `ACCEPT_ANY_SCHEMA`: the connector does 
own schema alignment, but here the duplicate names come from Spark's own 
positional rename, not from the user's query. The connector receives `STRUCT<x, 
x, z>` for a struct whose field names were unique, and it cannot tell which `x` 
the user meant. On where the fix belongs: extra validation or reordering in 
schema evolution would stop the leftover `s.z`, but it would still hand the 
duplicate-named struct to `ACCEPT_ANY_SCHEMA` connectors, and it would affect 
every schema-evolution write rather than only column-list inserts. On error 
precedence: a check limited to collisions the rename creates keeps 
`INCOMPATIBLE_DATA_FOR_TABLE.AMBIGUOUS_COLUMN_NAME` for the inserts that hit it 
today. It only changes which error is reported when a statement that already 
fails also has another incompatibility. Since the duplicate names come from 
this PR's default-on rename, could the check go into `renameFieldsInStruct` in 
thi
 s PR rather than a follow-up?
   
   <!-- SPARK_DEV_REVIEW_REPLY 
{"feedback_id":"inline:4385327697","thread_id":"inline:4385327697","verdict_sha256":"a7c3f790e62651fdb1c068c6fb250ef7e26f159546f4b9574e8663002c51bb67"}
 -->



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