comphead commented on code in PR #5293:
URL: https://github.com/apache/datafusion-comet/pull/5293#discussion_r3759555734


##########
spark/src/main/scala/org/apache/comet/serde/operator/CometWriteFiles.scala:
##########
@@ -0,0 +1,178 @@
+/*
+ * 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.serde.operator
+
+import java.net.URI
+import java.util.Locale
+
+import org.apache.parquet.hadoop.ParquetOutputFormat
+import org.apache.spark.sql.comet.{CometNativeExec, CometWriteFilesExec}
+import org.apache.spark.sql.execution.datasources.WriteFilesExec
+import org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormat
+import org.apache.spark.sql.internal.SQLConf
+
+import org.apache.comet.{CometConf, ConfigEntry}
+import org.apache.comet.CometSparkSessionExtensions.{isSpark40Plus, 
withFallbackReason}
+import org.apache.comet.objectstore.NativeConfig
+import org.apache.comet.rules.CometExecRule
+import org.apache.comet.serde.{CometOperatorSerde, Incompatible, 
OperatorOuterClass, SupportLevel, Unsupported}
+import org.apache.comet.serde.OperatorOuterClass.Operator
+import org.apache.comet.serde.QueryPlanSerde.serializeDataType
+
+/**
+ * Serde for Spark's `WriteFilesExec`, replacing the per-task Parquet write 
with Comet's native
+ * writer while leaving the surrounding write framework (commit protocol, 
stats trackers, SaveMode
+ * handling, `_SUCCESS`) to Spark. See [[CometWriteFilesExec]] for how the two 
fit together.
+ */
+object CometWriteFiles extends CometOperatorSerde[WriteFilesExec] {
+
+  private val supportedCompressionCodecs =
+    Set("none", "uncompressed", "snappy", "lz4", "zstd", "gzip")
+
+  override def enabledConfig: Option[ConfigEntry[Boolean]] =
+    Some(CometConf.COMET_NATIVE_PARQUET_WRITE_ENABLED)
+
+  // Native writes require Arrow-formatted input data. If the query falls back 
to Spark
+  // (e.g., due to unsupported complex types), the write must also fall back.
+  override def requiresNativeChildren: Boolean = true
+
+  override def getSupportLevel(op: WriteFilesExec): SupportLevel = {
+    // `V1WritesUtils.getWriteFilesOpt` matches the `WriteFilesExecBase` trait 
on Spark 4.0+, which
+    // is what makes Spark route the write through CometWriteFilesExec. Spark 
3.x matches the
+    // concrete `WriteFilesExec` case class instead, so a Comet node would be 
silently ignored and
+    // the write would fall into FileFormatWriter's non-planned, row-based 
branch.
+    if (!isSpark40Plus) {
+      return Unsupported(Some("Native Parquet writes require Spark 4.0 or 
later"))

Review Comment:
   so Spark 3.x falls back to JVM writes? 



##########
spark/src/main/scala/org/apache/comet/serde/operator/CometWriteFiles.scala:
##########
@@ -0,0 +1,178 @@
+/*
+ * 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.serde.operator
+
+import java.net.URI
+import java.util.Locale
+
+import org.apache.parquet.hadoop.ParquetOutputFormat
+import org.apache.spark.sql.comet.{CometNativeExec, CometWriteFilesExec}
+import org.apache.spark.sql.execution.datasources.WriteFilesExec
+import org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormat
+import org.apache.spark.sql.internal.SQLConf
+
+import org.apache.comet.{CometConf, ConfigEntry}
+import org.apache.comet.CometSparkSessionExtensions.{isSpark40Plus, 
withFallbackReason}
+import org.apache.comet.objectstore.NativeConfig
+import org.apache.comet.rules.CometExecRule
+import org.apache.comet.serde.{CometOperatorSerde, Incompatible, 
OperatorOuterClass, SupportLevel, Unsupported}
+import org.apache.comet.serde.OperatorOuterClass.Operator
+import org.apache.comet.serde.QueryPlanSerde.serializeDataType
+
+/**
+ * Serde for Spark's `WriteFilesExec`, replacing the per-task Parquet write 
with Comet's native
+ * writer while leaving the surrounding write framework (commit protocol, 
stats trackers, SaveMode
+ * handling, `_SUCCESS`) to Spark. See [[CometWriteFilesExec]] for how the two 
fit together.
+ */
+object CometWriteFiles extends CometOperatorSerde[WriteFilesExec] {
+
+  private val supportedCompressionCodecs =
+    Set("none", "uncompressed", "snappy", "lz4", "zstd", "gzip")
+
+  override def enabledConfig: Option[ConfigEntry[Boolean]] =
+    Some(CometConf.COMET_NATIVE_PARQUET_WRITE_ENABLED)
+
+  // Native writes require Arrow-formatted input data. If the query falls back 
to Spark
+  // (e.g., due to unsupported complex types), the write must also fall back.
+  override def requiresNativeChildren: Boolean = true
+
+  override def getSupportLevel(op: WriteFilesExec): SupportLevel = {
+    // `V1WritesUtils.getWriteFilesOpt` matches the `WriteFilesExecBase` trait 
on Spark 4.0+, which
+    // is what makes Spark route the write through CometWriteFilesExec. Spark 
3.x matches the
+    // concrete `WriteFilesExec` case class instead, so a Comet node would be 
silently ignored and
+    // the write would fall into FileFormatWriter's non-planned, row-based 
branch.
+    if (!isSpark40Plus) {
+      return Unsupported(Some("Native Parquet writes require Spark 4.0 or 
later"))
+    }
+
+    if (!op.fileFormat.isInstanceOf[ParquetFileFormat]) {
+      return Unsupported(Some("Only Parquet writes are supported"))
+    }
+
+    // The write node does not carry the output path, so CometExecRule tags it 
from the enclosing
+    // InsertIntoHadoopFsRelationCommand. An absent tag means this write 
belongs to some other V1
+    // write command (a Hive insert, for example) whose semantics Comet has 
not been verified
+    // against, so decline it.
+    val outputPath = outputPathOf(op) match {
+      case Some(path) => path
+      case None =>
+        return Unsupported(Some("Only InsertIntoHadoopFsRelationCommand writes 
are supported"))
+    }
+
+    if (!outputPath.startsWith("file:") && !outputPath.startsWith("hdfs:")) {

Review Comment:
   we need also fallback for dynamicPartitionOverwrite



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