dongjoon-hyun commented on PR #58412:
URL: https://github.com/apache/spark/pull/58412#issuecomment-5528646817

   Follow-up review of c845783a906 against the latest `master` (bcea2b23caa). 
Items already covered by the existing threads and my earlier comment are 
excluded. All findings are established from source; no runtime reproduction was 
attempted.
   
   ### Test fixtures (this PR)
   
   **1. [P2] `InMemoryRowLevelOperationTable` did not receive the 
identity-transform restriction** (`InMemoryRowLevelOperationTable.scala`, 
`filterAttributes`)
   After the review fixes, the V1/V2/Catalyst fixtures advertise only 
identity-transform sources, but the row-level fixture still returns 
`partitioning.flatMap(_.references())` while sharing the same 
`CatalystRuntimeFilteringScan` evaluator that binds only identity slots. With 
the new `createTable(columns, transforms)` overload, a `bucket(4, dep)` or 
`days(...)` row-level table gets a group filter injected and recorded, but 
`filter()` returns early on `partAttrs.isEmpty` and prunes nothing, so a future 
`checkReplacedPartitions` assertion would rewrite every partition and fail 
without pointing at the fixture asymmetry. Suggest using 
`identityPartitionReferences` here as well, or documenting why row-level 
differs.
   
   **2. [P3] The test name "transformed partition source cannot be declared 
fully pushed" implies a Spark-side guard that does not exist** 
(`DataSourceV2CatalystRuntimeFilterSuite.scala`)
   The test exercises no rejection: the fixture's 
`fullyPushedFilterAttributes()` silently drops `part` via 
`identityPartitionAttrs`, and `checkFullyPushedFilterAttrs` only rejects nested 
references. A real connector partitioned by `days(part)` that lists `part` in 
`fullyPushedFilterAttributes()` still passes validation, `DataSourceV2Strategy` 
drops the post-scan `FilterExec`, and the scan compares a date against a day 
ordinal. Suggest renaming the test to describe the fixture behavior, or adding 
a Spark-side guard and a test for it.
   
   **3. [P3] `InMemoryCatalystRuntimeFilterTable.fullyPushedFilterAttributes()` 
advertises an unused test hook** (`InMemoryCatalystRuntimeFilterTable.scala`)
   It switched from `filterAttributes().filter(...)` to 
`identityPartitionAttrs.filter(...)`, and the new comment says a table can now 
declare a fully pushed attribute outside `filterAttributes()`, "a combination 
the interface forbids". No test sets both `filter-attributes` and 
`fully-pushed-filter-attributes`, so the hook is unused and `partitionAttrs` / 
`identityPartitionAttrs` are near-duplicates to keep in sync. 
`filterAttributes().filter(ref => identityRefs.contains(ref) && 
fullyPushedFilterAttrs.contains(...))` covers the actual need without the extra 
helper or the comment.
   
   **4. [P3] `expectedFilterPaths` duplicates `expectedFilterAttrs`** 
(`RowLevelOperationCatalystRuntimeFilterSuiteBase.scala`, 
`assertCatalystGroupFilter`)
   `expectedFilterAttrs` is already asserted equal to 
`scan.filterAttributes().map(_.fieldNames.mkString("."))`, so both new callers 
pass the same information twice (`Seq("dep.name")` and `Some(Seq(Seq("dep", 
"name")))`). `expectedFilterAttrs.map(_.split('.').toSeq)` works for every 
existing call site and lets the two nested tests drop the extra argument.
   
   **5. [P3] ~40 unchanged lines re-indented in `InMemoryBatchScan.filter` and 
`InMemoryTableWithV2Filter.filter`**
   Both bodies were wrapped in `partitioning match { case 
Array(IdentityTransform(ref)) => ... case _ => }`, adding a nesting level to 
every existing line although the only semantic change is that the single 
transform must be an identity. `git blame` on both bodies now points at this 
backport instead of the SPARK-56467 history, and later cherry-picks across 
branches will conflict on every line. A two-line change to the original guard 
keeps the body intact: `if (partitioning.length == 1 && 
identityPartitionReferences.length == 1) { val ref = 
identityPartitionReferences.head; ... }`.
   
   ### Interface docs (same text exists on master; best fixed upstream)
   
   **6. [P3] Root-attribute eligibility is documented as a contract rather than 
current behavior** (`SupportsRuntimeFiltering.java`, 
`SupportsRuntimeV2Filtering.java`, `SupportsRuntimeCatalystFiltering.scala`)
   Eligibility is `references.subsetOf(AttributeSet)` in `PartitionPruning`, 
`DataSourceV2Strategy` and `PushDownUtils`, so a scan advertising 
`derives.toStr` also receives predicates on `derives.other`. Beyond the 
connector-side burden the new docs describe, this injects a 
`DynamicPruningSubquery` for a join on the sibling field, runs (and may 
broadcast) the build side, and the source then ignores the pushed filter. 
Results stay correct, but no test observes the DPP path (the "sibling" test 
covers only scalar subqueries). Since path-aware eligibility is deferred to 
SPARK-59095, the Javadoc could say Spark "currently" tracks eligibility by root 
attribute rather than stating it as the interface contract.
   
   Generated-by: Claude Fable 5.1
   


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