Copilot commented on code in PR #12964:
URL: https://github.com/apache/gluten/pull/12964#discussion_r4312786476


##########
gluten-substrait/src/main/scala/org/apache/gluten/execution/BasicScanExecTransformer.scala:
##########
@@ -177,12 +177,20 @@ trait BasicScanExecTransformer extends 
LeafTransformSupport with BaseDataSource
     doNativeValidation(substraitContext, relNode)
   }
 
+  protected def isRowIndexMetadataColumn(attr: Attribute): Boolean = {
+    
BackendsApiManager.getSparkPlanExecApiInstance.isRowIndexMetadataColumn(attr.name)
+  }
+
+  protected def isNativeMetadataColumn(attr: Attribute): Boolean = {
+    attr.isMetadataCol || getMetadataColumns().exists(_.exprId == attr.exprId)

Review Comment:
   `isNativeMetadataColumn` calls `getMetadataColumns()` for every attribute 
processed by `makeColumnTypeNode`. If `getMetadataColumns()` is non-trivial or 
allocates, this can become O(n²) over the output columns. Consider caching 
metadata exprIds once (e.g., a `lazy val metadataExprIdSet = 
getMetadataColumns().map(_.exprId).toSet`) and using set membership here.



##########
gluten-iceberg/src/main/scala/org/apache/iceberg/spark/source/GlutenIcebergSourceUtil.scala:
##########
@@ -46,12 +46,18 @@ object GlutenIcebergSourceUtil {
   private val InputFileBlockLengthCol = "input_file_block_length"
 
   def isSupportedScan(sparkScan: Scan): Boolean = sparkScan match {
-    case _: SparkBatchQueryScan | _: SparkStagedScan => true
+    case _: SparkBatchQueryScan | _: SparkStagedScan | _: SparkCopyOnWriteScan 
=> true
     case _ => false
   }
 
   def isSparkStagedScan(sparkScan: Scan): Boolean = 
sparkScan.isInstanceOf[SparkStagedScan]
 
+  def isSparkCopyOnWriteScan(sparkScan: Scan): Boolean =
+    sparkScan.isInstanceOf[SparkCopyOnWriteScan]
+
+  def hasOrcFiles(sparkScan: Scan): Boolean =
+    asFileScanTask(getScanTasks(sparkScan)).exists(_.file().format() == 
FileFormat.ORC)
+

Review Comment:
   `hasOrcFiles` eagerly converts all scan tasks to `FileScanTask` (and 
`asFileScanTask` does multiple full passes via `forall`), then checks `exists`. 
For copy-on-write MERGE/UPDATE/DELETE on large tables, this validation can 
become expensive during planning. Consider a single-pass traversal that 
short-circuits as soon as an ORC task is found, and avoid materializing a full 
`List[FileScanTask]`.



##########
.github/workflows/util/iceberg-upstream/flaky-tests.csv:
##########
@@ -16,5 +16,7 @@
 # All invocations of these methods run and are reported, but do not affect the 
gate.
 # Use exact class and method names; omit method arguments and invocation 
indices.
 class,method
-# Example
-# 
org.apache.iceberg.spark.extensions.TestAlterTablePartitionFields,testDropPartitionAndSourceColumnLong
+# Tests expect BatchScanExec, native uses IcebergScanTransformer soo these 
fail.
+org.apache.iceberg.spark.extensions.TestCopyOnWriteDelete,testDeleteWithVectorizedReads
+org.apache.iceberg.spark.extensions.TestCopyOnWriteMerge,testMergeWithVectorizedReads
+org.apache.iceberg.spark.extensions.TestCopyOnWriteUpdate,testUpdateWithVectorizedReads

Review Comment:
   The comment indicates these tests fail deterministically due to plan-shape 
expectations (not flakiness). Adding them to a 'flaky' non-gating allowlist can 
mask real regressions. Prefer either (a) updating the upstream test expectation 
to allow `IcebergScanTransformer`/native planning, or (b) tracking these as 
known-incompatibilities with a linked issue and an explicit TODO/time horizon 
(or separate 'known failures' list) so they don’t silently accumulate.



##########
gluten-iceberg/src/main/scala/org/apache/gluten/execution/IcebergScanTransformer.scala:
##########
@@ -216,13 +208,28 @@ case class IcebergScanTransformer(
       !readSchemaFields.contains(name)
   }
 
+  private lazy val copyOnWriteFilePathMetadataColumns = output.filter {
+    attr => IcebergScanTransformer.isCopyOnWriteFilePathColumn(attr.name)
+  }
+
   override def getMetadataColumns(): Seq[AttributeReference] = {
-    val extraMetadataColumns = inputFileRelatedMetadataColumns.filterNot {
-      metadataAttr => 
metadataColumns.exists(_.name.equalsIgnoreCase(metadataAttr.name))
-    }
+    val extraMetadataColumns =
+      (inputFileRelatedMetadataColumns ++ 
copyOnWriteFilePathMetadataColumns).filterNot {
+        metadataAttr => 
metadataColumns.exists(_.name.equalsIgnoreCase(metadataAttr.name))
+      }
     metadataColumns ++ extraMetadataColumns
   }
 
+  override protected def isRowIndexMetadataColumn(attr: Attribute): Boolean = {
+    IcebergScanTransformer.isCopyOnWriteRowPositionColumn(attr.name) ||
+    super.isRowIndexMetadataColumn(attr)
+  }
+
+  override protected def isNativeMetadataColumn(attr: Attribute): Boolean = {
+    IcebergScanTransformer.isCopyOnWriteFilePathColumn(attr.name) ||
+    super.isNativeMetadataColumn(attr)
+  }

Review Comment:
   This introduces new classification rules that are critical for correctness 
of Iceberg copy-on-write MERGE/UPDATE/DELETE (mapping `row_position` to 
row-index and `file_path` to native metadata). Please add/extend an automated 
test that exercises a copy-on-write `MERGE INTO` plan end-to-end (or at least 
validates the planned scan output columns) to ensure these columns are 
recognized as intended, and that unsupported formats (e.g., ORC in 
copy-on-write) are rejected as expected.



##########
.github/workflows/util/iceberg-upstream/flaky-tests.csv:
##########
@@ -16,5 +16,7 @@
 # All invocations of these methods run and are reported, but do not affect the 
gate.
 # Use exact class and method names; omit method arguments and invocation 
indices.
 class,method
-# Example
-# 
org.apache.iceberg.spark.extensions.TestAlterTablePartitionFields,testDropPartitionAndSourceColumnLong
+# Tests expect BatchScanExec, native uses IcebergScanTransformer soo these 
fail.

Review Comment:
   Correct the typo 'soo' to 'so' in this comment.



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