LuciferYang commented on PR #58409:
URL: https://github.com/apache/spark/pull/58409#issuecomment-5541737696

   Thanks for staying on this, @cloud-fan, and you are right about the branch: 
`getOrInferFileFormatSchema` does catch the duplicate-column check and continue 
with a warning (`DataSource.scala:239-245`, SPARK-18108 and SPARK-21144). I had 
not found it, and my earlier replies answered the symptom rather than the 
mechanism, which is probably why the question kept coming back. Let me lay out 
what I read this time so you can tell me where it is wrong.
   
   As I read it there are two checks on the V1 path, looking at different 
things. The warn-and-continue one checks `(dataSchema ++ 
partitionSchema).map(_.name)`, so what it tolerates is a name shared between 
the data schema and the partition schema. The throwing one is 
`checkSchemaColumnNameDuplication(hs.dataSchema, equality)` in 
`resolveRelation`, and that is what a duplicate *inside* the data schema hits. 
It sits after the relation-building match and applies to its result, so every 
`HadoopFsRelation` branch goes through it, the streaming-sink metadata one and 
the `CatalogFileIndex` one included, and `equality` is `conf.resolver`.
   
   The tolerated case seems unable to leave two occurrences behind, because of 
`DataSource.scala:222-223`: a user-specified schema becomes the data schema 
minus every field whose name matches a partition column, so the field that made 
the concatenation ambiguous is the one that gets removed, and if the duplicated 
name is the partition column's own then both copies go. Printing the resolved 
relation's two schemas:
   
   ```
   user schema (a, p), partition column p:  loaded, data=a          
partition=p, rows=[2,2],[0,0],[1,1]
   user schema (p, p), partition column p:  loaded, data=<empty>    
partition=p, rows=[2],[0],[1]
   user schema (x, x), no partition column: AnalysisException 
[COLUMN_ALREADY_EXISTS] The column `x` already exists
   ```
   
   Two places did look like they could bite, and I think your instinct about 
the weak check is right about one of them. Streaming is where a duplicate 
really does travel on it: `readStream.schema("x int, x int")` survives stream 
setup, since `sourceSchema` goes through `getOrInferFileFormatSchema`. 
`FileStreamSource.getBatch` then builds each micro-batch with 
`resolveRelation(checkFilesExist = false, readOnly = true)`, so the query fails 
at first-batch planning rather than at analysis, which is worth its own JIRA 
even though no relation reaches `buildReader`. The other is 
`HiveMetastoreCatalog.convertToLogicalRelation`, the one construction site that 
skips the check outright, but it is only ever called with `ParquetFileFormat` 
or `OrcFileFormat`, and a Hive avro table stays a `HiveTableRelation` and reads 
through the Hive SerDe.
   
   So as far as I can tell `dataSchema.fieldIndex` is never asked to choose 
between two occurrences. You know this code much better than I do, though, so 
if there is a path I have walked past, please say which one and I will open a 
follow-up JIRA for the ordinal plumbing, since this PR is already merged and 
cannot carry the change anyway. A query I can run would help me see it fastest.
   


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