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


##########
sql/connect/common/src/main/scala/org/apache/spark/sql/connect/SparkSession.scala:
##########
@@ -223,7 +223,9 @@ class SparkSession private[sql] (
 
   /** @inheritdoc */
   def createDataFrame(rows: java.util.List[Row], schema: StructType): 
DataFrame = {
-    createDataset(RowEncoder.encoderFor(schema), 
rows.iterator().asScala).toDF()
+    // The client cannot observe the server's CHAR/VARCHAR configuration. 
Encode an explicitly

Review Comment:
   Fixed in 46f0f8dea49. The comment now specifically describes the 
client-local CHAR/VARCHAR semantics applied by RowEncoder and leaves other 
local encoder configuration out of scope.



##########
python/pyspark/sql/types.py:
##########
@@ -330,19 +330,31 @@ class CharType(AtomicType):
     ----------
     length : int
         the length limitation.
+    collation : str, optional

Review Comment:
   Fixed in 46f0f8dea49. Both parameter docs now state that None means no 
explicitly declared collation and is distinct from explicit UTF8_BINARY.



##########
python/pyspark/sql/types.py:
##########
@@ -330,19 +330,31 @@ class CharType(AtomicType):
     ----------
     length : int
         the length limitation.
+    collation : str, optional
+        name of the collation.
     """
 
-    def __init__(self, length: int):
+    def __init__(self, length: int, collation: Optional[str] = None):
         self.length = length
+        self.collation = collation
 
     def simpleString(self) -> str:
-        return "char(%d)" % (self.length)
+        if self.collation is None:
+            return "char(%d)" % (self.length)
+
+        return "char(%d) collate %s" % (self.length, self.collation)
 
     def jsonValue(self) -> str:
-        return "char(%d)" % (self.length)
+        return self.simpleString()
 
     def __repr__(self) -> str:

Review Comment:
   Fixed in 46f0f8dea49. The repr round-trip test now includes explicit 
UTF8_BINARY and non-binary collations for both CharType and VarcharType.



##########
python/pyspark/sql/types.py:
##########
@@ -2671,7 +2708,12 @@ def _parse_datatype_json_value(  # type: ignore[return]
 def _assert_valid_type_for_collation(
     fieldPath: str, fieldType: Any, collationMap: Dict[str, str]
 ) -> None:
-    if fieldPath in collationMap and fieldType != "string":
+    is_string_type = (
+        fieldType == "string"
+        or (isinstance(fieldType, str) and _LENGTH_CHAR.fullmatch(fieldType) 
is not None)

Review Comment:
   Fixed in 46f0f8dea49. Collation restoration metadata now accepts only 
uncollated char(n)/varchar(n) type text. Matching and conflicting 
inline-plus-metadata encodings are both covered as negative cases.



##########
sql/connect/common/src/main/scala/org/apache/spark/sql/connect/SparkSession.scala:
##########
@@ -223,7 +223,10 @@ class SparkSession private[sql] (
 
   /** @inheritdoc */
   def createDataFrame(rows: java.util.List[Row], schema: StructType): 
DataFrame = {
-    createDataset(RowEncoder.encoderFor(schema), 
rows.iterator().asScala).toDF()
+    // RowEncoder consults the client process's local SqlApiConf, which can 
differ from the
+    // server-side configuration visible through SparkSession.conf. Encode an 
explicitly provided
+    // schema independently of that local configuration, as for result schemas.
+    createDataset(RowEncoder.encoderForResultSchema(schema), 
rows.iterator().asScala).toDF()

Review Comment:
   Fixed in 46f0f8dea49. Explicit Row input now uses a collation-preserving 
physical STRING encoder while carrying the requested logical schema separately. 
Server-side reconciliation selects standard, legacy-as-string, or rejection 
behavior and builds the final attributes from that result. The E2E test covers 
empty and populated nested values, collations, standard padding/overflow, 
legacy unpadded STRING output, and default rejection.



##########
sql/connect/common/src/main/scala/org/apache/spark/sql/connect/SparkSession.scala:
##########
@@ -223,7 +223,9 @@ class SparkSession private[sql] (
 
   /** @inheritdoc */
   def createDataFrame(rows: java.util.List[Row], schema: StructType): 
DataFrame = {
-    createDataset(RowEncoder.encoderFor(schema), 
rows.iterator().asScala).toDF()
+    // The client cannot observe the server's CHAR/VARCHAR configuration. 
Encode an explicitly
+    // provided schema independently of the client's local configuration, as 
for result schemas.
+    createDataset(RowEncoder.encoderForResultSchema(schema), 
rows.iterator().asScala).toDF()

Review Comment:
   Fixed in 46f0f8dea49. Empty and populated input now share server-side policy 
reconciliation, including legacy charVarcharAsString output with unpadded 
physical values. The expanded E2E matrix covers standard, legacy, and default 
modes.



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