sunchao commented on code in PR #5452:
URL: https://github.com/apache/datafusion-comet/pull/5452#discussion_r3848123213


##########
spark/src/main/scala/org/apache/comet/serde/literals.scala:
##########
@@ -215,4 +225,104 @@ object CometLiteral extends CometExpressionSerde[Literal] 
with Logging {
     }
     listLiteralBuilder
   }
+
+  /**
+   * Rebuild a folded complex Literal as an equivalent tree of `CreateArray` / 
`CreateMap` over
+   * primitive-typed Literals, or `None` when the shape cannot be rebuilt. The 
native `Literal`
+   * proto carries scalars and nested `ListLiteral`s but no map values, so a 
Literal whose type
+   * contains a `MapType` has to be expanded before serialization. Teaching 
the proto to transport
+   * maps directly would remove the need for this rewrite and for the declines 
below:
+   * https://github.com/apache/datafusion-comet/issues/1937
+   *
+   * Declined shapes:
+   *   - Null values and empty top-level containers: a synthesized `Create*` 
with no children
+   *     cannot recover the original element type. Empty `ArrayType` literals 
still serialize via
+   *     `makeListLiteral`, which keeps the type.
+   *   - `StructType` at any depth. Native `CreateNamedStruct` builds a 1-row 
`StructArray`
+   *     whenever all of its children are scalars (`values_to_arrays`), which 
collides with the
+   *     surrounding batch's row count. Its proto message also carries no 
type, so Spark's
+   *     declared field nullability cannot survive the wire either way.
+   *   - Map key types whose Spark equality semantics native lookup cannot 
honor, see
+   *     [[hasUnsafeMapKeyType]].
+   *   - Folded maps with duplicate keys. The rebuilt `CreateMap` evaluates 
through
+   *     `ArrayBasedMapBuilder`, which throws under 
`MAP_KEY_DEDUP_POLICY=EXCEPTION`, where the
+   *     original literal had already folded cleanly.
+   */
+  private def expandComplexLiteral(expr: Literal): Option[Expression] = {
+    if (expr.value == null) return None
+    expr.dataType match {
+      case ArrayType(et, _) if needsExpansion(et) =>
+        val arr = expr.value.asInstanceOf[ArrayData]
+        if (arr.numElements() == 0) {
+          None
+        } else {
+          val elements = (0 until arr.numElements()).map(i => 
asNullable(literalAt(arr, i, et)))
+          Some(CreateArray(elements, useStringTypeWhenEmpty = false))
+        }
+      case MapType(kt, vt, _) =>
+        val mapData = expr.value.asInstanceOf[MapData]
+        val keys = mapData.keyArray()
+        if (mapData.numElements() == 0 || hasUnsafeMapKeyType(kt) ||
+          hasDuplicateMapKeys(keys, kt)) {
+          None
+        } else {
+          val values = mapData.valueArray()
+          val children = (0 until keys.numElements()).flatMap(i =>
+            Seq(literalAt(keys, i, kt), asNullable(literalAt(values, i, vt))))

Review Comment:
   [P2] Preserve map-value nullability when expanding folded literals
   
   Could reconstruction retain the literal's declared `valueContainsNull`? With 
normal constant folding and a Parquet table containing `id` values 1, 2, 3:
   
   ```sql
   SELECT id, array(map(1, 2), map(2, coalesce(id, 0))) AS a
   FROM t
   ```
   
   Both original array children have `MapType(IntegerType, IntegerType, 
false)`, so the existing array type check passes. Wrapping the folded map's 
value in `KnownNullable` changes only that reconstructed map to 
`valueContainsNull=true`. The dynamic sibling stays `false`, and native 
`make_array` panics with `Arrays with inconsistent types passed to 
MutableArrayData`. Unlike the earlier non-folded constructor example, this 
rewrite introduces the mismatch after checking two identical input types.
   
   I reproduced this at `31f28b2e` on Spark 3.5.9 and 4.1.3 with native 
`CometProject` assertions. Replacing only the literal serializer with the exact 
base version restores Spark projection and the correct three-row result. Please 
preserve the declared map-value nullability and add a normal-folding regression 
test for this mixed literal/dynamic case.



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