Skip to content

Fix Spark master GpuBatchScanExec compile after replanWithRuntimeFilters API change[reduced-it] - #15932

Merged
firestarman merged 4 commits into
NVIDIA:mainfrom
firestarman:fix/15930-spark500-batchscan-keyed-partitioning
Sep 11, 2026
Merged

Fix Spark master GpuBatchScanExec compile after replanWithRuntimeFilters API change[reduced-it]#15932
firestarman merged 4 commits into
NVIDIA:mainfrom
firestarman:fix/15930-spark500-batchscan-keyed-partitioning

Conversation

@firestarman

@firestarman firestarman commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Fixes #15930.

Description

Spark master nightly builds fail in sql-plugin while compiling the Spark 5.0 shim: GpuBatchScanExec still passes outputPartitioning (Partitioning) into PushDownUtils.replanWithRuntimeFilters, which now takes Option[KeyedPartitioning]. Released Spark versions are unaffected. After this change, Spark 5 / master snapshot compilation succeeds again. No new configuration.

The helper must use the full-width keys the source reported, not the planner view. outputPartitioning may project away pruned key columns and is the wrong type. GPU GpuBatchScanExec now passes reportedKeyedPartitioning from DataSourceV2ScanExecBase, matching Spark's BatchScanExec.

The same Spark 5 BatchScanExec also treats pruned-out partition keys as planner metadata: equals, hashCode, and doCanonicalize use prunedKeyGroupedPartitioning, and canonicalize uses normalizeExpressions so multi-key order is preserved (SPARK-58120). Those were ported as well so GPU AQE reuse / sameResult does not diverge from CPU, and so a canonicalized keyed scan cannot reorder Integer/String keys.

Compile and the Spark 5 suite were checked with mvn -f scala2.13/pom.xml -Dbuildver=500 -Dcuda.version=cuda13 -pl sql-plugin,tests -am package -DwildcardSuites=com.nvidia.spark.rapids.shims.GpuBatchScanExecCanonicalizeSuite (BUILD SUCCESS, 4 tests). GpuBatchScanExecCanonicalizeSuite covers dangling-key equality, sameResult across different ExprIds, SPARK-58120 key order, and SPARK-59248-style runtime-filter replanning after a pruned leading key (filteredPartitions on a keyed GpuScan). Spark 5 unit tests use the Iceberg stub, so that last case is a GpuScan with HasPartitionKey partitions rather than an Iceberg query. Existing Spark 4 Iceberg SPJ / DSv2 scan tests still cover the Iceberg runtime-filter path.

This change was drafted with AI assistance. A human reviewed the diff and this description before updating the PR.

Checklists

Documentation

  • Updated for new or modified user-facing features or behaviors
  • No user-facing change

Testing

  • Added or modified tests to cover new code paths
  • Covered by existing tests
  • Not required

Performance

  • Tests ran and results are added in the PR description
  • Issue filed with a link in the PR description
  • Not required

Driver-side plan identity and a compile-time argument swap when building scan partitions. No per-row or executor GPU work is added. reportedKeyedPartitioning is already the lazy value outputPartitioning is derived from in Spark's DataSourceV2ScanExecBase.

Spark master now takes Option[KeyedPartitioning] and requires the
full-width reported keys, not the possibly projected outputPartitioning.

Signed-off-by: Firestarman <firestarmanllc@gmail.com>
@firestarman firestarman added bug Something isn't working SQL part of the SQL/Dataframe plugin labels Sep 9, 2026
@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no outstanding correctness or repository-rule issues identified.

Summary

  • Passes full-width reported keyed partitioning to runtime-filter replanning.
  • Excludes pruned partition keys from plan identity and canonicalization.
  • Preserves multi-key expression order during canonicalization.
  • Adds Spark 5 coverage for plan equality, canonicalization, and runtime-filter replanning.
  • Corrects the new test suite’s import ordering.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Source-reported full-width keys] --> B[GpuBatchScanExec]
  B --> C[Runtime-filter replanning]
  C --> D[Filtered partitions with original key slots]
  B --> E[Prune keys absent from output]
  E --> F[Plan equality and hash code]
  E --> G[Order-preserving canonicalization]
Loading

Reviews (4) · Last reviewed commit: "Fix scalastyle import order in GpuBatchS..."

Ignore pruned-out partition keys in equals/hashCode and canonicalize
with normalizeExpressions so key order is preserved (SPARK-58120).

Signed-off-by: Firestarman <firestarmanllc@gmail.com>
@firestarman firestarman changed the title Fix Spark master GpuBatchScanExec compile after replanWithRuntimeFilters API change[fast-ut][reduced-it] Fix Spark master GpuBatchScanExec compile after replanWithRuntimeFilters API change[reduced-it] Sep 9, 2026
@firestarman firestarman self-assigned this Sep 9, 2026
@firestarman

Copy link
Copy Markdown
Collaborator Author

build

@firestarman
firestarman requested a review from a team September 9, 2026 06:08
outputPartitioning,
// Full-width keys as the source reported them. outputPartitioning may project
// pruned key columns away and is a Partitioning, not Option[KeyedPartitioning].
reportedKeyedPartitioning,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Could we add an end-to-end regression test for the full-width key behavior exercised here? The new suite never evaluates filteredPartitions, and the existing Iceberg DPP case uses a single, unpruned partition key. An implementation that passes None or the pruned keys here would therefore still pass the current tests, while a runtime-filter replan after pruning a leading key can misalign keyed partitions, return wrong rows, or throw ClassCastException. Please port the SPARK-59248-style query with a multi-column key, a pruned leading key, and a runtime filter, and assert CPU/GPU result equality plus the GPU scan/SPJ plan.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a Spark 5 suite case that actually evaluates filteredPartitions. It uses a keyed GpuScan whose partitions implement HasPartitionKey with (store_id, dept_id), prunes the leading store_id from scan output, and applies a runtime filter on dept_id (SPARK-59248 shape). The test asserts padded None slots, remaining keys still two fields wide, and only dept_id=10 kept.

Spark 5 unit tests compile against the Iceberg stub, so this is not an Iceberg SQL IT. Passing None or the pruned one-column planner keys here fails the keyed replan (misaligned HasPartitionKey rows) rather than staying green.

keyGroupedPartitioning = keys)
}

test("equals and hashCode ignore partition keys pruned out of output") {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Could this be covered through Spark's actual plan-comparison path? These assertions call equals, hashCode, and doCanonicalize directly, so they do not verify the AQE reuse / sameResult behavior claimed in the PR description. Please add a query that produces semantically equivalent scans with different ExprIds and assert sameResult or ReusedExchangeExec; that would catch integration issues between canonicalization and physical-plan reuse.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dangling-key case now also asserts sameResult, which goes through SparkPlan.canonicalized (the path AQE reuse uses). There is a second test that builds two GpuBatchScanExecs that differ only by ExprId and asserts sameResult between them.

A ReusedExchangeExec SQL query is not added here: Spark 5 UTs do not have a GPU DSv2 source that reports HasPartitionKey (parquet file partitions do not implement it; Iceberg is stubbed). sameResult on the GPU scan nodes is what would decide reuse for those plans.

import org.apache.spark.sql.connector.read.{Batch, InputPartition, PartitionReaderFactory}
import org.apache.spark.sql.types.{IntegerType, StringType, StructType}

class GpuBatchScanExecCanonicalizeSuite extends SparkQueryCompareTestSuite with MockitoSugar {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] PR description issue (anchored here because it describes validation for this suite): mvn ... validate stops before compile and test, so the listed command does not support "Compile was checked." Please replace it with an actual compile, package, install, or test command and its result. For example, a Spark 5 / Scala 2.13 reactor install followed by this targeted suite would substantiate both compilation and test coverage.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the PR description. Compile and this suite were checked with:

mvn -f scala2.13/pom.xml -Dbuildver=500 -Dcuda.version=cuda13 -pl sql-plugin,tests -am package -DwildcardSuites=com.nvidia.spark.rapids.shims.GpuBatchScanExecCanonicalizeSuite

That package run compiled sql-plugin + tests and reported BUILD SUCCESS with 4 tests in GpuBatchScanExecCanonicalizeSuite.

Evaluate filteredPartitions after a pruned leading key plus runtime
filter, and assert sameResult through SparkPlan canonicalization.

Signed-off-by: Firestarman <firestarmanllc@gmail.com>
Signed-off-by: Firestarman <firestarmanllc@gmail.com>
@firestarman

Copy link
Copy Markdown
Collaborator Author

build

@res-life res-life left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@firestarman

Copy link
Copy Markdown
Collaborator Author

build

@firestarman
firestarman merged commit 3f731d7 into NVIDIA:main Sep 11, 2026
57 checks passed
@firestarman
firestarman deleted the fix/15930-spark500-batchscan-keyed-partitioning branch September 11, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working SQL part of the SQL/Dataframe plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Spark master build fails: GpuBatchScanExec.scala spark500 shim type mismatch (Partitioning vs Option[KeyedPartitioning])

3 participants