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


##########
sql/hive/src/main/scala/org/apache/spark/sql/hive/hiveUDFEvaluators.scala:
##########
@@ -162,9 +162,12 @@ class HiveGenericUDFEvaluator(
   }
 
   @transient
-  private lazy val unwrapper: Any => Any = unwrapperFor(returnInspector)
+  private lazy val catalystReturnType = inspectorToDataType(returnInspector)

Review Comment:
   **Blocking (P1):** `catalystReturnType` is transient, so this recomputes it 
from the executor's current `SQLConf`; the new wrapper branches also reject an 
already-resolved `CharType`/`VarcharType` when the caller has first-class types 
disabled. A view created under the persisted standard-semantics flag can 
therefore be analyzed as `CHAR(5)` but execute with STRING converters, losing 
padding and length checks or passing a different writable class to the Hive 
function. Please carry the analyzed result and intermediate types through 
evaluator serialization and select conversion from those types rather than 
`SQLConf.get`, with persisted-view coverage that analyzes and executes under 
opposite settings.
   
   **Recommended change:** Bind Hive conversion construction to the Catalyst 
types resolved during analysis.
   
   **Why this works:** Carry the resolved GenericUDF return type and UDAF 
partial-result types through evaluator serialization, and make target-aware 
wrappers select CHAR/VARCHAR behavior from their supplied DataType rather than 
the execution-time SQLConf.
   
   **Scope:** HiveInspectors conversion selection, transient Hive GenericUDF 
and UDAF evaluator schemas, and focused cross-session persisted-view tests.
   
   **Compatibility:** Legacy expressions analyzed as STRING remain on the 
legacy representation, while expressions analyzed as CHAR/VARCHAR retain their 
declared length, padding, and default-collation boundary regardless of the 
caller session.
   
   **Risks:** A serialized analyzed type must stay aligned with the Hive 
ObjectInspector used after evaluator reconstruction. Changing partial-result 
schema ownership must keep UDAF serialization and deserialization symmetric.
   
   **Constraints:** Preserve the existing unsupported Hive length errors and 
default-collation behavior. Do not derive a different Catalyst type from 
mutable caller configuration after analysis.
   
   **Success:** Persisted Hive UDF and UDAF expressions return values matching 
their analyzed CHAR/VARCHAR schemas when created and queried under opposite 
settings, while inverse legacy plans continue to use STRING conversion.



##########
sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveUDFSuite.scala:
##########
@@ -892,6 +892,42 @@ class HiveUDFSuite extends QueryTest with 
TestHiveSingleton {
     hiveContext.reset()
   }
 
+  test("SPARK-59277: Hive UDF and UDTF support first-class CHAR/VARCHAR") {
+    withSQLConf(SQLConf.CHAR_VARCHAR_STANDARD_SEMANTICS.key -> "true") {

Review Comment:
   **Non-blocking (P2):** The changed guards use `charVarcharFirstClassTypes`, 
which is also true when `preserveCharVarcharTypeInfo` is enabled and standard 
semantics is false, but all SPARK-59277 integration tests set only standard 
semantics. Please add a preserve-only `HiveUDFSuite` case that asserts both the 
first-class result type and the CHAR padding/value, so a regression that 
narrows these branches to standard semantics cannot pass.



##########
sql/hive/src/main/scala/org/apache/spark/sql/hive/execution/HiveScriptTransformationExec.scala:
##########
@@ -130,7 +132,7 @@ private[hive] case class HiveScriptTransformationExec(
           if (dataList.get(i) == null) {
             mutableRow.setNullAt(i)
           } else {
-            unwrappers(i)(dataList.get(i), mutableRow, i)
+            mutableRow.update(i, unwrappers(i)(dataList.get(i)))

Review Comment:
   **Non-blocking (P2):** This now routes every SerDe output value through `Any 
=> Any` and `SpecificInternalRow.update`, so primitive fields no longer use the 
existing `HiveStructField` unwrapper's direct `setBoolean`/`setInt`/`setLong` 
paths on this per-row loop. Please add a DataType-aware in-place overload that 
preserves the specialized primitive setters and uses target-type-aware generic 
conversion only for CHAR/VARCHAR and other types that need it.



##########
sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveInspectors.scala:
##########
@@ -829,6 +864,26 @@ private[hive] trait HiveInspectors {
             null
           }
         }
+      case (_, c: CharType) =>

Review Comment:
   **Nit (P3):** The Scaladoc above this overload still says every 
non-nanosecond target delegates to the `ObjectInspector`-only overload, but 
these new CHAR/VARCHAR branches pad values and reject excess length. Please 
update the contract to describe these target-type checks.



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