szehon-ho commented on code in PR #58412:
URL: https://github.com/apache/spark/pull/58412#discussion_r3897440150


##########
sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryCatalystRuntimeFilterTable.scala:
##########
@@ -74,23 +75,28 @@ class InMemoryCatalystRuntimeFilterTable(
       
Option(InMemoryCatalystRuntimeFilterTable.this.properties.get(FilterAttributesKey))
         .map(_.split(",").map(_.trim).toSet)
 
+    private val fullyPushedFilterAttrs: Set[String] = Option(
+      
InMemoryCatalystRuntimeFilterTable.this.properties.get(FullyPushedFilterAttributesKey))
+      .map(_.split(",").map(_.trim).toSet)
+      .getOrElse(Set.empty)
+
+    /** Partition source columns that are present in the scan read schema. */
+    private def partitionAttrs: Array[NamedReference] = {
+      partitioning.flatMap(_.references()).distinct
+        .filter(ref => readSchema.findNestedField(
+          ref.fieldNames.toImmutableArraySeq, resolver = 
SQLConf.get.resolver).isDefined)
+    }
+
     override def filterAttributes(): Array[NamedReference] = {
-      val scanFields = readSchema.fields.map(_.name).toSet
-      partitioning.flatMap(_.references()).filter { ref =>
-        val name = ref.fieldNames.mkString(".")
-        scanFields.contains(name) &&
-          restrictedFilterAttrs.forall(_.contains(name))
+      partitionAttrs.filter { ref =>
+        restrictedFilterAttrs.forall(_.contains(ref.fieldNames.mkString(".")))
       }
     }
 
+    // Not intersected with `filterAttributes()`, so a table can declare a 
fully pushed attribute
+    // that is not a filter attribute, a combination the interface forbids.
     override def fullyPushedFilterAttributes(): Array[NamedReference] = {
-      val fullyPushedFilterAttrs = Option(
-        
InMemoryCatalystRuntimeFilterTable.this.properties.get(FullyPushedFilterAttributesKey))
-        .map(_.split(",").map(_.trim).toSet)
-        .getOrElse(Set.empty)
-      filterAttributes().filter { ref =>
-        fullyPushedFilterAttrs.contains(ref.fieldNames.mkString("."))
-      }
+      partitionAttrs.filter(ref => 
fullyPushedFilterAttrs.contains(ref.fieldNames.mkString(".")))

Review Comment:
   Thanks. `fullyPushedFilterAttributes()` is now restricted to identity 
transforms, matching what the fixture evaluator can enforce directly. 
Non-identity sources may still receive ordinary Catalyst runtime filters, but 
Spark retains the post-scan residual filter. I added a `days(part)` regression 
verifying the runtime filter is pushed, both partitions remain at the source, 
and the residual returns only the matching date.



##########
sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTableWithV2Filter.scala:
##########
@@ -66,9 +67,9 @@ class InMemoryTableWithV2Filter(
     extends BatchScanBaseClass(_data, readSchema, tableSchema) with 
SupportsRuntimeV2Filtering {
 
     override def filterAttributes(): Array[NamedReference] = {
-      val scanFields = readSchema.fields.map(_.name).toSet
       partitioning.flatMap(_.references)
-        .filter(ref => scanFields.contains(ref.fieldNames.mkString(".")))
+        .filter(ref => readSchema.findNestedField(
+          ref.fieldNames.toImmutableArraySeq, resolver = 
SQLConf.get.resolver).isDefined)

Review Comment:
   Thanks, good catch. I restricted both public V1/V2 fixtures to advertise 
only identity-transform source attributes, and added the same identity guard in 
their evaluators. The shared regression uses `truncate(derives.toStr, 1)` and 
runs against both fixtures; it verifies no DPP filter is pushed on the 
transformed source and that all partitions remain available for the residual 
join.



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