dongjoon-hyun opened a new pull request, #59799:
URL: https://github.com/apache/spark/pull/59799

   [SPARK-60565][SQL] Fix reading and writing collated strings in Hive serde 
tables
   
   ### What changes were proposed in this pull request?
   
   This PR aims to remove the collations from the Hive column types in 
`HiveClientImpl.toHiveColumn`, which converts Spark columns into Hive columns.
   
   - Collated `STRING` types, including the nested ones in `ARRAY`, `STRUCT`, 
and `MAP`, become the regular `string` type via 
`SchemaUtils.replaceCollatedStringWithString`, like `HiveExternalCatalog` does 
before calling Hive metastore (SPARK-47873).
   - The raw `CHAR`/`VARCHAR` type string in the field metadata, e.g. `char(3) 
collate UTF8_LCASE`, loses its ` collate <name>` clauses. The type string is 
not parsed again, because the parsing depends on the session configurations. 
For example, `struct<a:char(3),b:timestamp>` would become 
`struct<a:char(3),b:timestamp_ntz>` with 
`spark.sql.timestampType=TIMESTAMP_NTZ`.
   
   ### Why are the changes needed?
   
   Hive has no collations. `HiveExternalCatalog` removes the collations before 
calling Hive metastore, so a Hive serde table with collated string columns is 
created with `string` columns in Hive metastore, and Spark restores the 
collations from the table properties. However, `InsertIntoHiveTable`, 
`InsertIntoHiveDirCommand`, and `HiveTableScanExec` build the Hive table from 
the Spark schema via `HiveClientImpl.toHiveTable`, and `toHiveColumn` uses 
`catalogString`, e.g. `string collate UNICODE_CI`. Hive SerDe fails to parse 
such column types (`columns.types`), so Spark fails to read and write the table.
   
   ```sql
   CREATE TABLE t (i INT, c STRING COLLATE UNICODE_CI) STORED AS TEXTFILE;
   INSERT INTO t VALUES (1, 'a');
   ```
   
   ```
   org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in 
stage 0.0 failed 1 times, most recent failure: Lost task 0.0 in stage 0.0 (TID 
0) (localhost executor driver): java.lang.IllegalArgumentException: Error: type 
expected at the position 4 of 'int:string collate UNICODE_CI' but 'string 
collate UNICODE_CI' is found.
   ```
   
   Hive SerDe fails in the same way with
   - `SELECT`, e.g. of the rows that Hive wrote,
   - `CREATE TABLE ... AS SELECT` and `DataFrameWriter.saveAsTable` with 
`format("hive")`, which also drop the new table,
   - `INSERT OVERWRITE [LOCAL] DIRECTORY` with Hive SerDe, e.g. `ROW FORMAT 
DELIMITED` or `STORED AS TEXTFILE`.
   
   It affects the `TEXTFILE`, `SEQUENCEFILE`, `RCFILE`, and `AVRO` tables, and 
the `ORC` and `PARQUET` tables when `spark.sql.hive.convertMetastoreOrc` and 
`spark.sql.hive.convertMetastoreParquet` are `false`. An explicit `COLLATE 
UTF8_BINARY` also fails because its `catalogString` is `string collate 
UTF8_BINARY`. This has been the behavior since such tables can be created 
(SPARK-47873, Apache Spark 4.0.0).
   
   For collated `CHAR`/`VARCHAR` types (SPARK-54870), the raw type string in 
the field metadata keeps the collations even after `HiveExternalCatalog` 
removes them from the data types. So the Hive metastore calls fail too, e.g. 
`ALTER TABLE ... ADD COLUMNS` on a table with a `CHAR(3) COLLATE UTF8_LCASE` 
column, and `CREATE TABLE ... STORED AS PARQUET AS SELECT * FROM` such a table.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. Spark reads and writes Hive serde tables with collated string columns, 
and `ALTER TABLE ... ADD COLUMNS` works on tables with collated 
`CHAR`/`VARCHAR` columns. Spark keeps the collations of the columns as before, 
and Hive reads the tables with the regular string types.
   
   Hive ORC and Parquet tables that Spark converts to the native data sources 
(`spark.sql.hive.convertMetastoreOrc` and 
`spark.sql.hive.convertMetastoreParquet`, both `true` by default) don't use 
Hive SerDe, so this PR doesn't change them.
   
   ### How was this patch tested?
   
   Pass the CIs with the newly added test cases.
   - `HiveSerDeReadWriteSuite`: reads and writes collated `STRING`, `ARRAY`, 
`STRUCT`, `MAP`, `CHAR`, and `VARCHAR` columns via Hive and Spark, and CTAS for 
all Hive serde formats.
   - `InsertSuite`: `INSERT OVERWRITE LOCAL DIRECTORY` with collated strings.
   - `AlterTableAddColumnsSuite`: `ALTER TABLE ... ADD COLUMNS` on a table with 
collated `CHAR` and `VARCHAR` columns.
   - `HiveClientImplSuite`: `toHiveColumn` removes the collations, and keeps 
`timestamp` with `spark.sql.timestampType=TIMESTAMP_NTZ`.
   
   The new tests in `HiveSerDeReadWriteSuite` and `InsertSuite` fail without 
this fix.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Opus 5.5


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