srielau commented on code in PR #58080:
URL: https://github.com/apache/spark/pull/58080#discussion_r3817090734


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CollationTypeCoercion.scala:
##########
@@ -115,6 +123,8 @@ object CollationTypeCoercion extends SQLConfHelper {
 
         expr match {
           case lit: Literal => lit.copy(dataType = newDataType)
+          case cast: Cast if needsCharPaddingCast(cast.dataType, newDataType) 
=>
+            Cast(cast, newDataType, timeZoneId = 
Some(conf.sessionLocalTimeZone))
           case cast: Cast => cast.copy(dataType = newDataType)

Review Comment:
   Fixed in dddd721.
   
   `changeType` always nests `Cast(existingCast, lct)` and no longer retargets. 
Analyzer goldens for `COALESCE(CAST('abcdef' AS VARCHAR(2)), CAST('x' AS 
VARCHAR(4)))` now show `cast(cast(abcdef as varchar(2)) as varchar(4))` and the 
result is `ab`. Numeric `CAST(12345 AS VARCHAR(4))` inside COALESCE still 
raises `EXCEED_LIMIT_LENGTH`; `try_cast` still yields NULL then the sibling. 
Same coverage for CASE / IN and a collated VARCHAR COALESCE. Those cases are 
also in the SPARK-58802 dual-run matrix.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/basicLogicalOperators.scala:
##########
@@ -184,7 +184,24 @@ object Project {
         if (other == target) {
           col
         } else if (Cast.canANSIStoreAssign(other, target)) {
-          Cast(col, target, Option(conf.sessionLocalTimeZone), ansiEnabled = 
true)
+          // Store assignment must not use character-to-character CAST 
truncation (ISO 6.13).
+          // Cast to unconstrained STRING first, then apply the write-side 
length check.
+          // Avoid replaceCharVarcharWithString: first-class types keep 
CHAR/VARCHAR.
+          val (castTarget, lengthCheckType) = target match {
+            case c: CharType => (c.toStringType, Some(c: DataType))
+            case v: VarcharType => (v.toStringType, Some(v: DataType))
+            case otherType => (otherType, None)
+          }
+          val casted = if (other == castTarget) {
+            col
+          } else {
+            Cast(col, castTarget, Option(conf.sessionLocalTimeZone), 
ansiEnabled = true)
+          }
+          if (lengthCheckType.isDefined && !conf.charVarcharAsString) {

Review Comment:
   Fixed in dddd721.
   
   Write-side length checks now use 
`CharVarcharUtils.shouldApplyWriteSideLengthCheck`: skip only on the legacy 
`charVarcharAsString` path without first-class types. `standardSemantics` (and 
preserve) still apply the check when the legacy flag is also on. 
`TableOutputResolver` and default-column evaluation use the same helper. Added 
a combined-flag `Dataset.to` / `INSERT` regression test.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/ToStringBase.scala:
##########
@@ -58,12 +58,16 @@ trait ToStringBase { self: UnaryExpression with 
TimeZoneAwareExpression =>
   // Returns a function to convert a value to pretty string. The function 
assumes input is not null.
   protected final def castToString(
       from: DataType, to: StringConstraint = NoConstraint): Any => UTF8String =
-    to match {
-      case FixedLength(length) =>
+    (to, from) match {
+      case (FixedLength(length), _: StringType) if 
SQLConf.get.charVarcharStandardSemantics =>
+        s => CharVarcharCodegenUtils.charTypeCast(castToString(from)(s), 
length)
+      case (MaxLength(length), _: StringType) if 
SQLConf.get.charVarcharStandardSemantics =>

Review Comment:
   Fixed in dddd721.
   
   Truncation in `ToStringBase` is gated on `Cast.USER_SPECIFIED_CAST` (already 
set by the parser, `Column.cast`, and Connect). Implicit / store-assignment 
Casts keep the write-side length check. `ToPrettyString` stays on the 
write-side path. Project still goes through STRING then `stringLengthCheck` so 
`Dataset.to` does not depend on a tagged Cast.



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