dongjoon-hyun commented on code in PR #55579:
URL: https://github.com/apache/spark/pull/55579#discussion_r4048745686


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/FileScan.scala:
##########
@@ -186,6 +209,47 @@ trait FileScan extends Scan
     partitions.toArray
   }
 
+  /**
+   * The partition columns Spark can derive a runtime filter on (SPARK-30628), 
restricted to the
+   * ones `readSchema()` still exposes: a reference missing from the scan 
relation output fails to
+   * resolve, and a pushed-down aggregate keeps only the partition columns it 
groups by.
+   *
+   * A filter over one of them is applied by selecting partition directories 
in `buildPartitions`,
+   * the same treatment a compile-time `partitionFilters` entry gets, so the 
scan evaluates it in
+   * full and Spark does not evaluate it again after the scan -- 
`FileScanBuilder.pushFilters`
+   * already keeps compile-time partition filters out of the post-scan filters 
for that reason.
+   * Directory selection matches a predicate's references against 
`fileIndex.partitionSchema` by
+   * name, so the names reported here have to be the ones that schema uses; 
both sides derive from
+   * it today, and a divergence would silently drop the predicate instead of 
failing.
+   */
+  override def filterAttributes(): Array[NamedReference] = {
+    val readFields = readSchema().fieldNames.map(normalizeName).toSet
+    readPartitionSchema.fieldNames
+      .filter(name => readFields.contains(normalizeName(name)))
+      .map(FieldReference.column)
+  }
+
+  override def fullyPushedFilterAttributes(): Array[NamedReference] = 
filterAttributes()
+
+  override def planInputPartitionsWithRuntimeFilters(
+      expressions: Array[Expression]): Array[InputPartition] = {
+    // Directory selection is the only thing that applies these, and it 
silently ignores a predicate
+    // whose references are not all partition columns -- which, for attributes 
declared fully
+    // pushed, would leave the predicate evaluated nowhere. Spark screens for 
that before it gets
+    // here; fail loudly rather than return wrong rows if that ever stops 
being true. Compare the
+    // way the file index does, by exact name against its own partition 
schema, so this guard cannot
+    // pass something the index will then drop.
+    val partitionNames = fileIndex.partitionSchema.fieldNames.toSet
+    val notApplicable = expressions.filterNot(
+      _.references.forall(a => partitionNames.contains(a.name)))
+    if (notApplicable.nonEmpty) {
+      throw SparkException.internalError("A file scan can only apply a runtime 
filter over its " +
+        s"partition columns 
${fileIndex.partitionSchema.fieldNames.mkString("[", ", ", "]")}, " +
+        s"got ${notApplicable.mkString(", ")}")
+    }
+    buildPartitions(partitionFilters ++ expressions).toArray

Review Comment:
   This path bypasses `partitions` / `planInputPartitions()` entirely. Since 
every `FileScan` now opts in by default (`filterAttributes()` and 
`fullyPushedFilterAttributes()` return the read partition columns), an existing 
3rd-party `FileScan` subclass that narrows the file set by overriding 
`partitions` will silently get the excluded files back as soon as DPP or a 
scalar-subquery filter fires. For the scalar-subquery case, the `FilterExec` 
above the scan is also removed, so nothing downstream masks it.
   
   This is different from the earlier answer in this thread ("existing sources 
see no behavior change"), and the PR description's user-facing section doesn't 
mention it either.
   
   Could we honor the overrides instead? For example, like V1, prune the 
`PartitionedFile`s already produced by `partitions` by evaluating the runtime 
filters on their `partitionValues` (bound to `readPartitionSchema`, which 
`filterAttributes()` already guarantees covers the referenced columns), then 
repack. That would also remove the duplicate driver-side listing/packing 
mentioned in the PR description. Alternatively, make the opt-in explicit per 
built-in format rather than the default for every `FileScan`.
   



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