philo-he commented on code in PR #12954:
URL: https://github.com/apache/gluten/pull/12954#discussion_r3939739304


##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -212,18 +233,32 @@ trait SparkShims {
       commonPartitionValues: Option[Seq[(InternalRow, Int)]],
       applyPartialClustering: Boolean,
       replicatePartitions: Boolean,
-      joinKeyPositions: Option[Seq[Int]] = None): Seq[Seq[InputPartition]] =
-    filteredPartitions
-
-  def extractExpressionTimestampAddUnit(timestampAdd: Expression): 
Option[Seq[String]] =
-    Option.empty
-
-  def extractExpressionTimestampDiffUnit(timestampDiff: Expression): 
Option[String] =
-    Option.empty
-
-  def withTryEvalMode(expr: Expression): Boolean = false
+      joinKeyPositions: Option[Seq[Int]] = None): Seq[Seq[InputPartition]]
+
+  def extractExpressionTimestampAddUnit(timestampAdd: Expression): 
Option[Seq[String]]
+
+  def withTryEvalMode(expr: Expression): Boolean = {
+    expr match {
+      case a: Add => a.evalMode == EvalMode.TRY
+      case s: Subtract => s.evalMode == EvalMode.TRY
+      case d: Divide => d.evalMode == EvalMode.TRY
+      case m: Multiply => m.evalMode == EvalMode.TRY
+      case c: Cast => c.evalMode == EvalMode.TRY
+      case _ => false
+    }
+  }
 
-  def withAnsiEvalMode(expr: Expression): Boolean = false
+  def withAnsiEvalMode(expr: Expression): Boolean = {

Review Comment:
   It seems both `withAnsiEvalMode` and `withTryEvalMode` can be moved from 
this shim class, since no divergence among the supported Spark versions with 
Spark 3.3 removed. Perhaps, it would be better to move them to an existing or 
new util class.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -124,28 +133,18 @@ trait SparkShims {
       sparkPartitionId: Int,
       sparkAttemptNumber: Int,
       committer: FileCommitProtocol,
-      iterator: Iterator[InternalRow]): WriteTaskResult = {
-    throw new UnsupportedOperationException()
-  }
+      iterator: Iterator[InternalRow]): WriteTaskResult
 
-  def enableNativeWriteFilesByDefault(): Boolean = false
+  def enableNativeWriteFilesByDefault(): Boolean
 
-  // Planned V1 writes were introduced in Spark 3.4. Older versions do not 
expose a required
-  // ordering utility and keep the default empty ordering.
-  // TODO: Remove this shim after dropping Spark 3.3 support.
   def getV1WriteRequiredOrdering(
       outputColumns: Seq[Attribute],
       partitionColumns: Seq[Attribute],
       bucketSpec: Option[BucketSpec],
       options: Map[String, String],
-      numStaticPartitionCols: Int): Seq[SortOrder] = Seq.empty
+      numStaticPartitionCols: Int): Seq[SortOrder]
 
-  def broadcastInternal[T: ClassTag](sc: SparkContext, value: T): Broadcast[T] 
= {
-    // Since Spark 3.4, the `sc.broadcast` has been optimized to use 
`sc.broadcastInternal`.
-    // More details see SPARK-39983.
-    // TODO, remove this shim once we drop Spark3.3 and previous
-    sc.broadcast(value)
-  }
+  def broadcastInternal[T: ClassTag](sc: SparkContext, value: T): Broadcast[T]

Review Comment:
   Seems we can remove this shim API also.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -89,33 +91,40 @@ trait SparkShims {
       sparkSession: SparkSession,
       readFunction: PartitionedFile => Iterator[InternalRow],
       filePartitions: Seq[FilePartition],
-      fileSourceScanExec: FileSourceScanExec): FileScanRDD
+      fileSourceScanExec: FileSourceScanExec): FileScanRDD = {
+    new FileScanRDD(
+      sparkSession,
+      readFunction,
+      filePartitions,
+      new StructType(
+        fileSourceScanExec.requiredSchema.fields ++
+          fileSourceScanExec.relation.partitionSchema.fields),
+      fileSourceScanExec.fileConstantMetadataColumns
+    )
+  }
 
   def filesGroupedToBuckets(
       selectedPartitions: Array[PartitionDirectory]): Map[Int, 
Array[PartitionedFile]]
 
-  // Spark3.4 new add table parameter in BatchScanExec.
-  def getBatchScanExecTable(batchScan: BatchScanExec): Table
+  def getBatchScanExecTable(batchScan: BatchScanExec): Table = batchScan.table
 
-  // The PartitionedFile API changed in spark 3.4
   def generatePartitionedFile(
       partitionValues: InternalRow,
       filePath: String,
       start: Long,
       length: Long,
-      @transient locations: Array[String] = Array.empty): PartitionedFile
+      @transient locations: Array[String] = Array.empty): PartitionedFile =
+    PartitionedFile(partitionValues, SparkPath.fromPathString(filePath), 
start, length, locations)

Review Comment:
   Ditto to directly call the implementation on the call side and remove this 
shim API.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -184,20 +183,42 @@ trait SparkShims {
       file: PartitionedFile,
       metadataColumnNames: Seq[String] = Seq.empty): Map[String, String] = {
     val requested = metadataColumnNames.toSet
-    Seq(
+    val originMetadataColumn = Seq(
       InputFileName().prettyName -> file.filePath.toString,
       InputFileBlockStart().prettyName -> file.start.toString,
       InputFileBlockLength().prettyName -> file.length.toString
     ).collect { case (name, value) if requested.contains(name) => name -> 
value }.toMap
+    val metadataColumn: mutable.Map[String, String] = 
mutable.Map(originMetadataColumn.toSeq: _*)
+    val path = new Path(file.filePath.toString)
+    for (columnName <- metadataColumnNames) {
+      columnName match {
+        case FileFormat.FILE_PATH => metadataColumn += (FileFormat.FILE_PATH 
-> path.toString)
+        case FileFormat.FILE_NAME => metadataColumn += (FileFormat.FILE_NAME 
-> path.getName)
+        case FileFormat.FILE_SIZE =>
+          metadataColumn += (FileFormat.FILE_SIZE -> file.fileSize.toString)
+        case FileFormat.FILE_MODIFICATION_TIME =>
+          val fileModifyTime = TimestampFormatter
+            .getFractionFormatter(ZoneOffset.UTC)
+            .format(file.modificationTime * 1000L)
+          metadataColumn += (FileFormat.FILE_MODIFICATION_TIME -> 
fileModifyTime)
+        case FileFormat.FILE_BLOCK_START =>
+          metadataColumn += (FileFormat.FILE_BLOCK_START -> 
file.start.toString)
+        case FileFormat.FILE_BLOCK_LENGTH =>
+          metadataColumn += (FileFormat.FILE_BLOCK_LENGTH -> 
file.length.toString)
+        case _ =>
+      }
+    }
+    metadataColumn.toMap
   }
 
   // For compatibility with Spark-3.5.
   def getAnalysisExceptionPlan(ae: AnalysisException): Option[LogicalPlan]
 
-  def getKeyGroupedPartitioning(batchScan: BatchScanExec): 
Option[Seq[Expression]] = Option(Seq())
+  def getKeyGroupedPartitioning(batchScan: BatchScanExec): 
Option[Seq[Expression]] = {
+    batchScan.keyGroupedPartitioning

Review Comment:
   It looks like this method can be removed, and let 
`batchScan.keyGroupedPartitioning` be directly called on the caller side.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########


Review Comment:
   I posted some comments before being aware of this comment. I would like to 
do the further refactor to remove those shim APIs if their implementations are 
consistent across the supported Spark versions. We can move them to the caller 
side or a proper module (if the shim API implementation is a bit complex and 
they are called from two or more places) for meeting the dependency requirement.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -89,33 +91,40 @@ trait SparkShims {
       sparkSession: SparkSession,
       readFunction: PartitionedFile => Iterator[InternalRow],
       filePartitions: Seq[FilePartition],
-      fileSourceScanExec: FileSourceScanExec): FileScanRDD
+      fileSourceScanExec: FileSourceScanExec): FileScanRDD = {
+    new FileScanRDD(
+      sparkSession,
+      readFunction,
+      filePartitions,
+      new StructType(
+        fileSourceScanExec.requiredSchema.fields ++
+          fileSourceScanExec.relation.partitionSchema.fields),
+      fileSourceScanExec.fileConstantMetadataColumns
+    )
+  }
 
   def filesGroupedToBuckets(
       selectedPartitions: Array[PartitionDirectory]): Map[Int, 
Array[PartitionedFile]]
 
-  // Spark3.4 new add table parameter in BatchScanExec.
-  def getBatchScanExecTable(batchScan: BatchScanExec): Table
+  def getBatchScanExecTable(batchScan: BatchScanExec): Table = batchScan.table

Review Comment:
   Should this shim API be removed? Then, directly call batchScan.table on the 
caller side.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -184,20 +183,42 @@ trait SparkShims {
       file: PartitionedFile,
       metadataColumnNames: Seq[String] = Seq.empty): Map[String, String] = {
     val requested = metadataColumnNames.toSet
-    Seq(
+    val originMetadataColumn = Seq(
       InputFileName().prettyName -> file.filePath.toString,
       InputFileBlockStart().prettyName -> file.start.toString,
       InputFileBlockLength().prettyName -> file.length.toString
     ).collect { case (name, value) if requested.contains(name) => name -> 
value }.toMap
+    val metadataColumn: mutable.Map[String, String] = 
mutable.Map(originMetadataColumn.toSeq: _*)
+    val path = new Path(file.filePath.toString)
+    for (columnName <- metadataColumnNames) {
+      columnName match {
+        case FileFormat.FILE_PATH => metadataColumn += (FileFormat.FILE_PATH 
-> path.toString)
+        case FileFormat.FILE_NAME => metadataColumn += (FileFormat.FILE_NAME 
-> path.getName)
+        case FileFormat.FILE_SIZE =>
+          metadataColumn += (FileFormat.FILE_SIZE -> file.fileSize.toString)
+        case FileFormat.FILE_MODIFICATION_TIME =>
+          val fileModifyTime = TimestampFormatter
+            .getFractionFormatter(ZoneOffset.UTC)
+            .format(file.modificationTime * 1000L)
+          metadataColumn += (FileFormat.FILE_MODIFICATION_TIME -> 
fileModifyTime)
+        case FileFormat.FILE_BLOCK_START =>
+          metadataColumn += (FileFormat.FILE_BLOCK_START -> 
file.start.toString)
+        case FileFormat.FILE_BLOCK_LENGTH =>
+          metadataColumn += (FileFormat.FILE_BLOCK_LENGTH -> 
file.length.toString)
+        case _ =>
+      }
+    }
+    metadataColumn.toMap

Review Comment:
   Perhaps, it would be better to move this shim API to other existing or new 
util class.



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -89,33 +91,40 @@ trait SparkShims {
       sparkSession: SparkSession,
       readFunction: PartitionedFile => Iterator[InternalRow],
       filePartitions: Seq[FilePartition],
-      fileSourceScanExec: FileSourceScanExec): FileScanRDD
+      fileSourceScanExec: FileSourceScanExec): FileScanRDD = {
+    new FileScanRDD(
+      sparkSession,
+      readFunction,
+      filePartitions,
+      new StructType(
+        fileSourceScanExec.requiredSchema.fields ++
+          fileSourceScanExec.relation.partitionSchema.fields),
+      fileSourceScanExec.fileConstantMetadataColumns
+    )
+  }
 
   def filesGroupedToBuckets(
       selectedPartitions: Array[PartitionDirectory]): Map[Int, 
Array[PartitionedFile]]
 
-  // Spark3.4 new add table parameter in BatchScanExec.
-  def getBatchScanExecTable(batchScan: BatchScanExec): Table
+  def getBatchScanExecTable(batchScan: BatchScanExec): Table = batchScan.table
 
-  // The PartitionedFile API changed in spark 3.4
   def generatePartitionedFile(
       partitionValues: InternalRow,
       filePath: String,
       start: Long,
       length: Long,
-      @transient locations: Array[String] = Array.empty): PartitionedFile
+      @transient locations: Array[String] = Array.empty): PartitionedFile =
+    PartitionedFile(partitionValues, SparkPath.fromPathString(filePath), 
start, length, locations)
 
   def isWindowGroupLimitExec(plan: SparkPlan): Boolean = false
 
   def getWindowGroupLimitExecShim(plan: SparkPlan): WindowGroupLimitExecShim = 
null
 
   def getWindowGroupLimitExec(windowGroupLimitExecShim: 
WindowGroupLimitExecShim): SparkPlan = null
 
-  def getLimitAndOffsetFromGlobalLimit(plan: GlobalLimitExec): (Int, Int) = 
(plan.limit, 0)
-
-  def getLimitAndOffsetFromTopK(plan: TakeOrderedAndProjectExec): (Int, Int) = 
(plan.limit, 0)
+  def getLimitAndOffsetFromGlobalLimit(plan: GlobalLimitExec): (Int, Int)
 
-  def getExtendedColumnarPostRules(): List[SparkSession => Rule[SparkPlan]]
+  def getLimitAndOffsetFromTopK(plan: TakeOrderedAndProjectExec): (Int, Int)

Review Comment:
   It seems that the above two shims APIs can be removed now. And the 
implementation for them are consistent for Spark 3.4 and later versions now. 
Consider to use their implementations on the caller side. 



##########
shims/common/src/main/scala/org/apache/gluten/sql/shims/SparkShims.scala:
##########
@@ -89,33 +91,40 @@ trait SparkShims {
       sparkSession: SparkSession,
       readFunction: PartitionedFile => Iterator[InternalRow],
       filePartitions: Seq[FilePartition],
-      fileSourceScanExec: FileSourceScanExec): FileScanRDD
+      fileSourceScanExec: FileSourceScanExec): FileScanRDD = {
+    new FileScanRDD(
+      sparkSession,
+      readFunction,
+      filePartitions,
+      new StructType(
+        fileSourceScanExec.requiredSchema.fields ++
+          fileSourceScanExec.relation.partitionSchema.fields),
+      fileSourceScanExec.fileConstantMetadataColumns

Review Comment:
   Ditto to directly use the implementation on the caller side or move to a 
util class or method if it is called from two or more places.



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