Skip to content

[VL][DELTA] Support Delta CDF scan offload#12218

Open
malinjawi wants to merge 4 commits into
apache:mainfrom
malinjawi:codex/delta-cdf-offload
Open

[VL][DELTA] Support Delta CDF scan offload#12218
malinjawi wants to merge 4 commits into
apache:mainfrom
malinjawi:codex/delta-cdf-offload

Conversation

@malinjawi

@malinjawi malinjawi commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

Addresses #12195.

Delta CDF reads enter Spark as CDCReader.DeltaCDFRelation, so they do not initially have the normal FileSourceScanExec + DeltaParquetFileFormat shape that Gluten's existing Delta scan offload rule recognizes.

This PR adds a Gluten Delta planner strategy, wired from the Velox Delta component, that recognizes DeltaCDFRelation, expands it through Delta's own CDF batch planning path, and rewrites the original projection/filter attributes onto the expanded logical plan. After that, the existing Delta scan offload path can plan the underlying CDF file scans as DeltaScanTransformer.

The change is intentionally scoped to Gluten's Delta/Spark planning layer rather than Velox C++:

  • Add DeltaCDFScanStrategy for table_changes(...) and DataFrame readChangeFeed scans.
  • Add Delta-version helper shims for Delta 2.3, 2.4, 3.3, and 4.x API differences.
  • Register the planner strategy from VeloxDeltaComponent.
  • Add Delta regression coverage for insert/update/delete CDF rows, filter/projection handling, bounded version reads, DataFrame readChangeFeed, column mapping, and a startingVersion = 0 case.

One planner/test nuance: Delta CDF expansion can keep a Spark-side ExistingRDD branch for synthesized change rows, including on the tested update/delete CDF paths. The regression suite therefore compares results against vanilla Spark and asserts that the expanded CDF file scans are transformed to DeltaScanTransformer, rather than requiring the entire expanded CDF union to be globally fallback-free.

How was this patch tested?

Local checks used JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home.

  • git diff --check
  • ./dev/format-scala-code.sh check
  • ./build/mvn -pl gluten-delta -am -Pspark-3.5 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-4.0 -Pscala-2.13 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-4.1 -Pscala-2.13 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests test-compile

Earlier cross-version compile checks also passed before the test-expectation-only update:

  • ./build/mvn -pl gluten-delta -am -Pspark-3.3 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests -Dcheckstyle.skip=true -Dscalastyle.skip=true -Dspotless.check.skip=true test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-3.4 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests -Dcheckstyle.skip=true -Dscalastyle.skip=true -Dspotless.check.skip=true test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-3.5 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests -Dcheckstyle.skip=true -Dscalastyle.skip=true -Dspotless.check.skip=true test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-4.0 -Pscala-2.13 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests -Dcheckstyle.skip=true -Dscalastyle.skip=true -Dspotless.check.skip=true test-compile
  • ./build/mvn -pl gluten-delta -am -Pspark-4.1 -Pscala-2.13 -Pjava-17 -Pbackends-velox -Pdelta -DskipTests -Dcheckstyle.skip=true -Dscalastyle.skip=true -Dspotless.check.skip=true test-compile

Full native Velox runtime and benchmarking are left to CI / a native Gluten-optimized environment; this local checkout does not have cpp/build/releases/libgluten.so and the Velox external project build available.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: IBM BOB

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

3 similar comments
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi
malinjawi marked this pull request as ready for review June 1, 2026 18:50
@felipepessoto

Copy link
Copy Markdown
Contributor

Could you add a DV-enabled CDF regression test to confirm the behavior? Something like:

  CREATE TABLE t (id INT, name STRING) USING delta
  TBLPROPERTIES ('delta.enableChangeDataFeed'='true', 'delta.enableDeletionVectors'='true');
  INSERT INTO t VALUES (1,'v1'),(2,'v2'),(3,'v3');
  DELETE FROM t WHERE id = 2;
  SELECT id, name, _change_type FROM table_changes('t', 0);

compared against vanilla Spark (checkAnswer)

import org.apache.spark.sql.delta.BatchCDFSchemaEndVersion
import org.apache.spark.sql.delta.commands.cdc.CDCReader

object DeltaCDFRelationHelper {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do you know what happens in Delta 4.1/4.2/4.3? Would it take the code from 4.0 folder?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes @felipepessoto I checked the current Maven profile/source wiring:

  • spark-4.0 sets delta.version=4.0.1 and delta.binary.version=40
  • spark-4.1 sets delta.version=4.1.0 and delta.binary.version=40
  • the Delta profile adds sources from src-delta${delta.binary.version}/main/scala

So with the current profile setup, both Spark 4.0 / Delta 4.0.x and Spark 4.1 / Delta 4.1.x use gluten-delta/src-delta40/....

For future Delta 4.2 / 4.3 support, it depends on how those profiles are introduced. If they keep delta.binary.version=40, they will continue to use the same src-delta40 helper. If Delta changes the relevant CDF APIs and Gluten introduces a new binary bucket, then we should add a new version-specific helper.

This also relates to the earlier folder-activation discussion in #11924: supporting family-level folders like src-spark4 / src-delta4 would make this cleaner and avoid copying code across Spark/Delta 4.x profiles when the APIs stay compatible. I think that belongs in a separate Maven/source-layout refactor rather than in this CDF PR.

@malinjawi

Copy link
Copy Markdown
Contributor Author

Could you add a DV-enabled CDF regression test to confirm the behavior? Something like:

  CREATE TABLE t (id INT, name STRING) USING delta
  TBLPROPERTIES ('delta.enableChangeDataFeed'='true', 'delta.enableDeletionVectors'='true');
  INSERT INTO t VALUES (1,'v1'),(2,'v2'),(3,'v3');
  DELETE FROM t WHERE id = 2;
  SELECT id, name, _change_type FROM table_changes('t', 0);

compared against vanilla Spark (checkAnswer)

Thanks @felipepessoto good point! I agree this is worth covering explicitly.

I’ll add a focused DV-enabled CDF regression with delta.enableChangeDataFeed=true and delta.enableDeletionVectors=true, comparing table_changes(...) against vanilla Spark via the existing runAndCompare / checkAnswer path.

One important nuance: this PR is not intended to claim full native DV support. DV-backed Delta scan execution is still a separate active area in Gluten/Velox and may continue to fall back where native DV handling is not available. The goal of the regression here is to make sure enabling DV does not break the CDF planning path or result correctness.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

1 similar comment
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi
malinjawi force-pushed the codex/delta-cdf-offload branch from 2cd31c0 to bca92ba Compare June 16, 2026 09:46
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi
malinjawi force-pushed the codex/delta-cdf-offload branch from bca92ba to b14394d Compare June 16, 2026 16:30
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

// DeltaScanTransformer).
private def touchesDeletionVectors(cdfRelation: CDCReader.DeltaCDFRelation): Boolean =
cdfRelation.snapshotWithSchemaMode.snapshot.metadata.configuration
.get("delta.enableDeletionVectors")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This table property says if new writes can write DV. But I think you want to find if table has any DV

@malinjawi malinjawi Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch; you were right that the table property only controls future writes. This is now addressed in two layers:

  • 3b462034a makes DeltaCDFScanStrategy inspect AddFile/RemoveFile actions only in the requested CDF version range.
  • Spark 3.4 CI then exposed an older physical fallback that still treated a DV-capable TahoeFileIndex as if every CDF range contained a DV. 049e608a3 now special-cases CdcAddFileIndex and TahoeRemoveFileIndex there as well, using their exact files/actions before the generic table-level fallback.

The regression covers both directions: a DV-enabled table's insert-only 0..1 range must offload, while a range containing a DV-backed delete must fall back even after delta.enableDeletionVectors is set back to false, with the CDF rows checked for correctness. Formatting and test compilation pass for Spark 3.3, 3.4, 3.5, 4.0, and 4.1.

Delta change-data-feed reads enter Spark as a CDCReader.DeltaCDFRelation,
which does not have the FileSourceScanExec + DeltaParquetFileFormat shape
that Gluten's Delta scan offload recognizes. Add a Gluten Delta planner
strategy (wired from VeloxDeltaComponent) that recognizes DeltaCDFRelation,
expands it through Delta's own CDF batch planning, and rewrites the
projection/filter attributes onto the expanded plan, so the existing Delta
scan offload path can plan the underlying CDF file scans as
DeltaScanTransformer.

CDF over a deletion-vector-enabled table is kept on Spark: native CDF lacks
the DV-aware row-level reconciliation, so an offloaded CDF scan would emit
still-live rows as `delete` change rows. Re-planning Delta's analyzed CDF
batch plan also drops that reconciliation on some Delta versions (Delta 2.4 /
Spark 3.4), where the remove side would surface every row of a logically
removed file as a `delete` change row. The planner strategy therefore declines
to intercept CDF reads whose table has deletion vectors enabled and leaves them
to Delta's own DeltaCDFRelation scan, which reconciles DVs correctly on every
supported Delta version; DeltaScanTransformer additionally guards both CDF scan
sides -- the add side (CdcAddFileIndex) and the remove side
(TahoeRemoveFileIndex) -- as a backstop. Normal (non-CDF) DV scans are
unaffected and continue to apply the DV natively.

Addresses apache#12195.
@malinjawi
malinjawi force-pushed the codex/delta-cdf-offload branch from b14394d to 582641a Compare June 16, 2026 19:36
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Inspect AddFile and RemoveFile actions in the requested CDF version range instead of relying on the table property, which only controls future DV writes.\n\nCover both DV-enabled ranges without DV actions and existing DV actions after the property is disabled.
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@malinjawi
malinjawi requested a review from felipepessoto July 19, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants