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


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/orc/OrcUtils.scala:
##########
@@ -536,11 +558,14 @@ object OrcUtils extends Logging {
       resultSchema: StructType,
       partitionSchema: StructType,
       conf: Configuration): String = {
-    val resultSchemaString = if (canPruneCols) {
-      OrcUtils.getOrcSchemaString(resultSchema)
+    val readSchema = if (canPruneCols) {
+      resultSchema
     } else {
-      OrcUtils.getOrcSchemaString(StructType(dataSchema.fields ++ 
partitionSchema.fields))
+      StructType(dataSchema.fields ++ partitionSchema.fields)
     }
+    // Spark CHAR/VARCHAR in the read schema are Catalyst constraints; ask ORC 
for STRING.
+    val resultSchemaString =
+      OrcUtils.getOrcSchemaString(orcReadSchemaWithoutCharVarchar(readSchema))

Review Comment:
   **Non-blocking (P2):** This rewrite runs whenever first-class CHAR/VARCHAR 
types are enabled. That includes the released 
`spark.sql.preserveCharVarcharTypeInfo` (4.0.0), not only standard semantics. 
Before this change ORC got `varchar(n)`/`char(n)` here, and its string-group 
conversion truncated STRING-stored values to `n`. In preserve-only mode Spark 
adds no read-side VARCHAR check (`addPaddingForScan` only pads CHAR there), so 
nothing takes over from ORC.
   
   Concretely: with `preserveCharVarcharTypeInfo=true` and standard semantics 
off, `spark.read.schema("v VARCHAR(4)").orc(p)` over a stored `abcdef` used to 
return `abcd` on the default vectorized reader. It now returns `abcdef` in a 
`VARCHAR(4)` column, with no error. CHAR(4) behaves the same way.
   
   Keeping the physical read independent of session flags looks intentional, 
and it matches Parquet. However, the PR description says the user-facing change 
is limited to unreleased standard semantics. The new preserve-only result is 
not declared in the `preserveCharVarcharTypeInfo` doc or a migration note, and 
no test pins it: the preserve-only assertions added here only compare schemas.
   
   **Recommended change:** Keep the mode-independent STRING reader and make the 
preserve-only outcome explicit. (1) Extend the PRESERVE_CHAR_VARCHAR_TYPE_INFO 
doc to say that ORC reads with CHAR/VARCHAR schemas over STRING storage return 
stored values without ORC truncation (as Parquet does), and that read-side 
length checks apply only under spark.sql.charVarchar.standardSemantics.enabled. 
(2) Add a SQL migration guide entry for the preserve-only ORC behavior change. 
(3) Add preserve-only ORC value tests in the CHAR/VARCHAR test family. (4) The 
PR description's user-facing-change section should mention the preserve-only 
change.
   
   **Why this works:** The physical ORC read stays independent of session 
flags, which preserves the single interpretation that fixed the cross-mode 
cache identity problems. The config contract and migration guide declare the 
new preserve-only outcome, and value-level tests make it a pinned, intentional 
behavior rather than an incidental one.
   
   **Scope:** Documentation of the released preserve-only config and migration 
guide, plus preserve-only ORC value tests; no production code change.
   
   **Compatibility:** The mode-independent ORC reader schema and 
standard-semantics read-side checks.
   
   **Risks:** Users of the experimental preserve flag who relied on ORC 
truncation will see longer values; the migration note must say so and point to 
standard semantics for read-side checks.
   
   **Constraints:** Do not reintroduce execution-time SQLConf reads into the 
ORC reader schema. Keep standard-semantics EXCEED_LIMIT_LENGTH and padding 
behavior unchanged.
   
   **Success:** The PRESERVE_CHAR_VARCHAR_TYPE_INFO doc and the migration guide 
state that preserve-only ORC reads over STRING storage are not truncated and 
that read-side length checks require standard semantics. A preserve-only ORC 
read of a stored abcdef value with a VARCHAR(4) schema returns abcdef in 
vectorized and row readers for V1 and V2, and the test fails if ORC truncation 
returns. Standard-semantics ORC reads of the same data still raise 
EXCEED_LIMIT_LENGTH.
   
   **Verification:**
   - **Behavior:** In preserve-only mode, ORC reads with over-length VARCHAR 
and CHAR schemas over STRING-stored data return the stored values (CHAR padded 
when shorter) across vectorized and row readers and V1/V2 sources.
   - **Compatibility:** Under standard semantics the same reads raise 
EXCEED_LIMIT_LENGTH, and default-mode ORC reads are unchanged.
   - **Inspection:** The preserveCharVarcharTypeInfo config documentation and 
the migration guide describe the preserve-only ORC read outcome and how it 
relates to standard semantics.



##########
sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveCharVarcharTestSuite.scala:
##########
@@ -54,12 +55,22 @@ class HiveCharVarcharTestSuite extends CharVarcharTestSuite 
with TestHiveSinglet
     }
   }
 
-  test("SPARK-35700: Read char/varchar orc table with created and written by 
external systems") {
+  test("SPARK-35700, SPARK-58814: read native char/varchar ORC") {
     withTable("t") {
       hiveClient.runSqlHive("CREATE TABLE t(c CHAR(5), v VARCHAR(7)) STORED AS 
ORC")
-      hiveClient.runSqlHive("INSERT INTO t VALUES('Spark', 'kyuubi')")
-      checkAnswer(sql("SELECT c, v from t"), Row("Spark", "kyuubi"))
-      checkAnswer(sql("SELECT v from t where c = 'Spark' and v = 'kyuubi'"), 
Row("kyuubi"))
+      hiveClient.runSqlHive("INSERT INTO t VALUES('Sp', 'kyuubi')")
+      Seq(true, false).foreach { vectorizedReaderEnabled =>
+        withSQLConf(
+            SQLConf.CHAR_VARCHAR_STANDARD_SEMANTICS.key -> "true",

Review Comment:
   **Nit (P3):** Every assertion now runs under standard semantics, so the 
default-configuration case that SPARK-35700 fixed is no longer tested. That 
case is a pushed `v = 'kyuubi'` predicate over a Hive-written native ORC 
`varchar(7)` column, read through `convertMetastoreOrc`. Under standard 
semantics both `c` and `v` are wrapped in read-side checks, so neither 
predicate reaches `OrcFilters`. No other Hive test pushes a predicate over 
native ORC CHAR/VARCHAR in default mode.
   
   Because this PR edits `OrcFilters.getPredicateLeafType` and the ORC schema 
code, a default-mode pushdown regression would now pass CI. Could you keep a 
default-configuration iteration, with the original `'Spark'`/`'kyuubi'` data 
and predicate, next to the new standard-semantics one?
   
   **Verification:**
   - **Regression:** A default-configuration read of a Hive-written native ORC 
CHAR(5)/VARCHAR(7) table with a pushed VARCHAR equality predicate returns the 
expected row, and fails if default-mode pushdown or schema stripping regresses.



##########
sql/core/src/test/scala/org/apache/spark/sql/CharVarcharTestSuite.scala:
##########
@@ -1976,17 +2138,6 @@ class BasicCharVarcharTestSuite extends 
SharedSparkSession {
           assert(spark.read.orc(path).schema.head.dataType === StringType)
         }
       }
-      // preserveCharVarcharTypeInfo also keeps first-class types, so write 
still stamps CHAR.

Review Comment:
   **Nit (P3):** This was the only test that wrote ORC with 
`preserveCharVarcharTypeInfo` on and standard semantics off, then checked that 
a file-only read infers `CHAR(4)`. The preserve-only round trip added earlier 
for the review request on `OrcUtils` (write first-class CHAR/VARCHAR, reload 
without a schema) is gone too.
   
   Every ORC write in the changed tests now runs under standard semantics. The 
preserve-only reads only compare the schemas of files written in standard mode, 
and the generic `CharVarcharTestSuite` variants run on parquet and DSV2, not 
ORC. So if preserve-only writes stopped stamping `spark.sql.catalyst.type`, no 
test would fail.
   
   Could you add back a preserve-only ORC write followed by a file-only read 
that asserts the inferred `CHAR(4)`/`VARCHAR(4)` types?
   
   **Verification:**
   - **Regression:** A preserve-only ORC write of CHAR(4)/VARCHAR(4) values 
reloads with constrained types inferred, and fails if preserve-only writes stop 
stamping spark.sql.catalyst.type.



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