andygrove commented on code in PR #5631:
URL: https://github.com/apache/datafusion-comet/pull/5631#discussion_r3917748442


##########
spark/src/main/scala/org/apache/spark/sql/comet/util/Utils.scala:
##########
@@ -49,6 +49,9 @@ import org.apache.comet.shims.CometTypeShim
 import org.apache.comet.vector.CometVector
 
 object Utils extends CometTypeShim with Logging {
+  private val ArrowExtensionNameKey = "ARROW:extension:name"

Review Comment:
   Arrow Java already defines this key as 
`ArrowType.ExtensionType.EXTENSION_METADATA_KEY_NAME`. Could we use that 
instead of a local literal? One less string that has to stay in sync by hand.



##########
spark/src/main/scala/org/apache/comet/rules/CometExecRule.scala:
##########
@@ -826,15 +827,23 @@ case class CometExecRule(session: SparkSession)
       handler: CometOperatorSerde[_]): Option[SparkPlan] = {
     val serde = handler.asInstanceOf[CometOperatorSerde[SparkPlan]]
     if (isOperatorEnabled(serde, op)) {
+      val dataProducingChildren = op.children.flatMap {
+        case writeFiles: WriteFilesExec => Seq(writeFiles.child)
+        case other => Seq(other)
+      }
+      if (!op.isInstanceOf[CometScanExec] &&
+        (op.output ++ dataProducingChildren.flatMap(_.output)).exists(attr =>
+          containsVariantType(attr.dataType))) {
+        withFallbackReason(
+          op,
+          "Native operators do not support schemas containing type 
VariantType")
+        return None
+      }

Review Comment:
   Could you say more about why `CometScanExec` is exempted here? As far as I 
can tell `CometScanRule` only produces a `CometScanExec` after 
`CometScanTypeChecker` has approved every output type, and this PR's own test 
asserts that checker rejects `VariantType` and `ArrayType(VariantType)`, so I 
could not find a plan where the exemption changes anything.
   
   What makes me want to pin this down is that the same change removes the 
other guard on that path. `CometNativeScan.convert` gates on `scanTypes.length 
== scan.output.length`, and before this PR a Variant output made that length 
check fail and the scan decline with "unsupported Comet operator ... due to 
unsupported data types above". Now that `serializeDataType` succeeds for 
Variant, that check can never fire for Variant either. So `CometScanExec` ends 
up being the one operator where both the old implicit guard and the new 
explicit guard disappear in the same commit.
   
   If there is a real case behind the exemption, could we get a comment and a 
test that fails without it? If there is not, I would rather drop it. An 
unexplained hole in a deny gate tends to become load-bearing later. It also 
reads oddly next to `CometBatchScanExec` on the Iceberg path, which is not 
exempted.



##########
spark/src/test/scala/org/apache/comet/CometVariantTypeSuite.scala:
##########
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.comet
+
+import java.util.Collections
+
+import scala.collection.mutable.ListBuffer
+import scala.jdk.CollectionConverters._
+
+import org.scalatest.funsuite.AnyFunSuite
+
+import org.apache.arrow.vector.types.pojo.{ArrowType, Field, FieldType}
+import org.apache.spark.sql.catalyst.expressions.AttributeReference
+import org.apache.spark.sql.comet.util.Utils
+import org.apache.spark.sql.types.{ArrayType, BinaryType, StructField, 
StructType}
+
+import org.apache.comet.rules.CometScanTypeChecker
+import org.apache.comet.serde.{CometAttributeReference, QueryPlanSerde, 
Unsupported}
+
+class CometVariantTypeSuite extends AnyFunSuite {
+  private val storageType = StructType(
+    Seq(
+      StructField("value", BinaryType, nullable = false),
+      StructField("metadata", BinaryType, nullable = false)))
+
+  private def variantField(extensionName: Option[String]): Field = {
+    val metadata = extensionName
+      .map(name => Collections.singletonMap("ARROW:extension:name", name))
+      .getOrElse(Collections.emptyMap[String, String]())
+    val children = Seq(
+      Field.notNullable("value", ArrowType.Binary.INSTANCE),
+      Field.notNullable("metadata", ArrowType.Binary.INSTANCE))
+    new Field(
+      "v",
+      new FieldType(true, ArrowType.Struct.INSTANCE, null, metadata),
+      children.asJava)
+  }
+
+  test("Variant identity requires the canonical Arrow extension marker") {

Review Comment:
   The marker name is now a literal in two places that have to agree, here and 
`Utils.VariantExtensionName`, and nothing in the PR ties either of them to 
arrow-rs. `has_valid_extension_type::<VariantType>()` will not catch drift 
either, because arrow-rs's `supports_data_type` accepts any `Struct`. So if 
`VariantType::NAME` ever changes, all four tests in this PR still pass while 
the real path quietly degrades to `StructType`. That silent degrade is the 
exact failure this PR exists to prevent, so it would be good to have something 
that fails loudly instead.
   
   Could the Rust test assert `VariantType::NAME == "arrow.parquet.variant"` 
directly? That is cheap and pins the upstream side. Beyond that, is a test that 
actually crosses the boundary feasible here, serializing a Spark `VariantType` 
schema through `QueryPlanSerde.serializeDataType`, running it through native, 
and asserting `Utils.fromArrowField` gives back `VariantType`? I realize no 
operator can carry Variant yet so this may need a narrow test hook, but the JVM 
to native contract is the whole point of the PR, and right now each half is 
only tested against a hand-written copy of the other half's assumptions.
   
   For what it is worth I did check that the pieces line up today. arrow-rs 
58.4.0 has `NAME = "arrow.parquet.variant"` in 
`parquet-variant-compute/src/variant_array.rs`, and Arrow Java 18.3.0's 
`SchemaImporter.importField` keeps unregistered extension metadata on the 
imported field rather than stripping it, so the marker should survive C Data 
import.



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