Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
bcb624c
feat: add JVM-planned native Delta Lake scan contrib module
dwsmith1983 Sep 3, 2026
5b22bd5
Merge branch 'main' into feature/delta-native-scan
andygrove Sep 12, 2026
1d91656
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 12, 2026
6430f93
fix: contain provider link failures, gate Hadoop-only S3 endpoints, a…
dwsmith1983 Sep 14, 2026
8090726
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 14, 2026
499adbf
Merge remote-tracking branch 'fork/feature/delta-native-scan' into fe…
dwsmith1983 Sep 14, 2026
519bfa8
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 14, 2026
02df40a
fix: keep every leaf requested when the name fold fails during rebase…
dwsmith1983 Sep 14, 2026
55c49e7
ci: activate the delta profile for the prerequisite installs and set …
dwsmith1983 Sep 15, 2026
6039c30
perf: pass null-free modern batches through the rebase untouched with…
dwsmith1983 Sep 15, 2026
b238a98
chore: drop redundant interpolators flagged by scalafix
dwsmith1983 Sep 15, 2026
68dd8e3
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 15, 2026
dcacee4
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 16, 2026
b3cd071
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 16, 2026
32d3157
Merge remote-tracking branch 'origin/main' into feature/delta-native-…
dwsmith1983 Sep 17, 2026
d21f5d4
ci: save the Delta contrib Maven caches on main only
dwsmith1983 Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ tiers partition the list and that the `pr` tier is exactly the default profile.
(Spark 4.1 profile only) pr_benchmark_check run-benchmark-check
delta_build_gate run-delta-build-gate
pyarrow_udf_test run-pyarrow-udf-tests
delta_contrib run-delta-tests
spark_4_1 run-spark-4.1-tests
label or dispatch only spark_4_1 sql_hive run-spark-4.1-hive-tests
---------------------- iceberg_1_11 run-iceberg-tests
Expand Down Expand Up @@ -152,6 +153,7 @@ tiers partition the list and that the `pr` tier is exactly the default profile.
| `pr_benchmark_check` | merge group, **or** PR with `run-benchmark-check` | benchmark sources only |
| `delta_build_gate` | merge group, **or** PR with `run-delta-build-gate` | main sources, poms, `contrib/delta` |
| `pyarrow_udf_test` | merge group, **or** PR with `run-pyarrow-udf-tests` | map-in-batch and Python runner code |
| `delta_contrib` | merge group, **or** PR with `run-delta-tests` | Delta contrib and native sources |
| `docs` | push to main, paths matched | `.asf.yaml`, `docs/**`, `docs.yaml` |
| `spark_3_5` | nightly, **or** PR with `run-spark-3.5-tests` | Spark 3.5 sources |
| `spark_4_1` | merge group, **or** PR with `run-spark-4.1-tests`; the `sql_hive` shards alone with `run-spark-4.1-hive-tests` | Spark 4.1 sources |
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ jobs:
iceberg_1_9: ${{ steps.compute.outputs.iceberg_1_9 }}
iceberg_1_10: ${{ steps.compute.outputs.iceberg_1_10 }}
iceberg_1_11: ${{ steps.compute.outputs.iceberg_1_11 }}
delta: ${{ steps.compute.outputs.delta }}
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -383,6 +384,15 @@ jobs:
spark-full: '3.5.9'
java: 17

delta_contrib:
name: Delta Contrib Tests
needs: changes
permissions:
contents: read
# Queue-only by default; PRs need the `run-delta-tests` label.
if: needs.changes.outputs.delta == 'true'
uses: ./.github/workflows/delta_contrib_test.yml

Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
spark_4_0:
name: Spark SQL Tests (Spark 4.0)
needs: changes
Expand Down Expand Up @@ -515,6 +525,7 @@ jobs:
- pyarrow_udf_test
- spark_3_4
- spark_3_5
- delta_contrib
- spark_4_0
- spark_4_1
- iceberg_1_8
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/delta_build_gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
# specific language governing permissions and limitations
# under the License.

# Build-gate verification for the optional contrib/delta integration.
# Build-gate verification for the Delta split of the native library and the JVM build.
#
# A single cheap job that runs dev/verify-contrib-delta-gate.sh, which proves:
# - the DEFAULT cargo / mvn / dylib build carries ZERO Delta surface
# (no comet-contrib-delta / delta_kernel in the cargo tree, no io.delta in
# the effective pom, no Delta symbols in libcomet); and
# - the kernel-backed `comet-contrib-delta` crate stays out of every shipped
# build (no comet-contrib-delta / delta_kernel in the default or
# --no-default-features cargo tree, no io.delta in the effective pom, no
# contrib symbols in libcomet), while the small default-on `delta` feature
# (deletion-vector decoding) is deliberately in and its symbol footprint is
# pinned; and
# - the gated build (`--features contrib-delta` / `-Pcontrib-delta`) compiles
# and pulls the right delta-spark per Spark profile.
#
Expand Down
263 changes: 263 additions & 0 deletions .github/workflows/delta_contrib_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: Delta Contrib Tests

# Reusable: invoked by ci.yml. Triggering, path filters, and concurrency
# live in the umbrella workflow.
on:
workflow_call:

permissions:
contents: read

env:
RUST_VERSION: stable
RUST_BACKTRACE: 1
# Force GNU ld on Linux: rust-lld cannot resolve -ljvm against the Zulu JDK
# layout installed by setup-java (same rationale as pr_build_linux.yml).
RUSTFLAGS: "-Clink-arg=-fuse-ld=bfd"
# The container's default locale is POSIX, which makes the JVM's file-path encoder
# reject non-ASCII partition directory names the suites create.
LANG: "C.UTF-8"
LC_ALL: "C.UTF-8"

jobs:

contrib-delta:
name: Delta contrib (Spark ${{ matrix.profile.spark }})
runs-on: ubuntu-24.04
container:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This container has no Docker socket, and CometDeltaS3Suite assume()s out when DockerClientFactory.isDockerAvailable is false, which scalatest reports as canceled and the build treats as green. So the MinIO suite contributes no coverage in CI even though the description lists it as live, and the S3 gate is the logic I would most like exercised end to end.

Could you either mount /var/run/docker.sock into this job (or run that one suite outside the container), or state in the workflow that the S3 suite is manual-only and drop it from the description's CI coverage claim?

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.

Could you either mount /var/run/docker.sock into this job (or run that one suite outside the container), or state in the workflow that the S3 suite is manual-only and drop it from the description's CI coverage claim?

Added a plain-runner job, contrib-delta-s3, that builds the same way and runs only CometDeltaS3Suite on Spark 3.5, where Testcontainers can start MinIO. The container matrix keeps the rest. I cannot exercise the workflow locally, so the first run here is the proof.

image: amd64/rust
strategy:
matrix:
profile:
- spark: "3.5"
java_version: "17"
- spark: "4.0"
java_version: "17"
- spark: "4.1"
java_version: "17"
# spark-4.2 is intentionally absent: the contrib profile is dormant
# until a Delta release supports Spark 4.2.
fail-fast: false
steps:
- uses: actions/checkout@v7

- name: Setup Rust & Java toolchain
uses: ./.github/actions/setup-builder
with:
rust-version: ${{ env.RUST_VERSION }}
jdk-version: ${{ matrix.profile.java_version }}

- name: Restore Maven dependencies
id: maven-cache
uses: actions/cache/restore@v6
with:
path: |
~/.m2/repository
/root/.m2/repository
key: ${{ runner.os }}-java-maven-${{ hashFiles('**/pom.xml') }}-delta-${{ matrix.profile.spark }}
restore-keys: |
${{ runner.os }}-java-maven-

- name: Restore Cargo cache
uses: actions/cache/restore@v6
with:
path: |
~/.cargo/registry
~/.cargo/git
native/target
key: ${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-${{ hashFiles('native/**/*.rs') }}
restore-keys: |
${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-

- name: Build native library (CI profile)
run: |
cd native
# `delta` is in the default feature set, so no feature flag is needed.
cargo build --profile ci
env:
# Must match the flags spark_sql_test_reusable.yml builds with:
# cargo folds RUSTFLAGS into its fingerprints, so any divergence
# would make the shared cargo cache restore without ever hitting.
RUSTFLAGS: "-Ctarget-cpu=x86-64-v3 -Clink-arg=-fuse-ld=bfd"

# No cache save: this workflow never runs on a push to main, so the restore above
# falls back to the cache build_linux saves there.

- name: Stage native library at release path
run: |
# Maven's -Prelease profile (activated below) expects libcomet.so
# under native/target/release/; --profile ci builds it under
# native/target/ci/ instead (same as the other native-building
# workflows), so copy it into place.
mkdir -p native/target/release
cp native/target/ci/libcomet.so native/target/release/libcomet.so

- name: Install Comet core jars
run: |
# The delta profile is what produces the spark test-jar the contrib suites depend on.
./mvnw -B -q -Prelease -Pspark-${{ matrix.profile.spark }},delta install -pl common,spark -DskipTests -Dspotless.check.skip=true

- name: Run Delta contrib test suites
run: |
SPARK_HOME=$(pwd) COMET_CONF_DIR=$(pwd)/conf ./mvnw -B -Prelease -Pspark-${{ matrix.profile.spark }},delta test -pl contrib/delta-spark

# Saved only on main: an entry written from a pull request or a
# `gh-readonly-queue/*` branch cannot be restored by any later run, and
# it evicts main's from the shared budget. See "Large caches are written
# on main only" in README.md.
- name: Save Maven dependencies
if: ${{ github.ref == 'refs/heads/main' && steps.maven-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v6
with:
path: |
~/.m2/repository
/root/.m2/repository
key: ${{ runner.os }}-java-maven-${{ hashFiles('**/pom.xml') }}-delta-${{ matrix.profile.spark }}

# The container jobs above have no Docker socket, so CometDeltaS3Suite cancels itself
# there. This job runs it on the plain runner, where Testcontainers can start MinIO.
contrib-delta-s3:
name: Delta contrib S3 suite (Spark 3.5, MinIO)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7

# setup-builder runs apt-get as root inside the container jobs; the hosted runner needs
# sudo for that, so the same steps are spelled out here.
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler clang

- name: Install JDK 17
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: "17"

- name: Setup Rust toolchain
run: |
rustup toolchain install ${{ env.RUST_VERSION }}
rustup default ${{ env.RUST_VERSION }}
rustup component add rustfmt clippy

- name: Restore Maven dependencies
id: maven-cache
uses: actions/cache/restore@v6
with:
path: |
~/.m2/repository
key: ${{ runner.os }}-java-maven-${{ hashFiles('**/pom.xml') }}-delta-3.5
restore-keys: |
${{ runner.os }}-java-maven-

- name: Restore Cargo cache
uses: actions/cache/restore@v6
with:
path: |
~/.cargo/registry
~/.cargo/git
native/target
key: ${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-${{ hashFiles('native/**/*.rs') }}
restore-keys: |
${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-

- name: Build native library (CI profile)
run: |
cd native
cargo build --profile ci
env:
RUSTFLAGS: "-Ctarget-cpu=x86-64-v3 -Clink-arg=-fuse-ld=bfd"

- name: Stage native library at release path
run: |
mkdir -p native/target/release
cp native/target/ci/libcomet.so native/target/release/libcomet.so

- name: Install Comet core jars
run: |
./mvnw -B -q -Prelease -Pspark-3.5,delta install -pl common,spark -DskipTests -Dspotless.check.skip=true

- name: Run the MinIO-backed S3 suite
run: |
docker info > /dev/null
SPARK_HOME=$(pwd) COMET_CONF_DIR=$(pwd)/conf ./mvnw -B -Prelease -Pspark-3.5,delta test -pl contrib/delta-spark -DwildcardSuites=org.apache.comet.contrib.delta.CometDeltaS3Suite

# Saved only on main, for the same reason as the container job above.
- name: Save Maven dependencies
if: ${{ github.ref == 'refs/heads/main' && steps.maven-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v6
with:
path: |
~/.m2/repository
key: ${{ runner.os }}-java-maven-${{ hashFiles('**/pom.xml') }}-delta-3.5

# `delta` is in the default feature set, so no regular job builds without it;
# this keeps the feature-off build and its "built without the delta feature"
# error arm (planner.rs cfg(not(feature = "delta"))) from becoming dead code.
feature-off-build:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: Feature-off native build
runs-on: ubuntu-24.04
container:
image: amd64/rust
steps:
- uses: actions/checkout@v7

- name: Setup Rust & Java toolchain
uses: ./.github/actions/setup-builder
with:
rust-version: ${{ env.RUST_VERSION }}
jdk-version: "17"

- name: Restore Cargo cache
uses: actions/cache/restore@v6
with:
path: |
~/.cargo/registry
~/.cargo/git
native/target
key: ${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-${{ hashFiles('native/**/*.rs') }}
restore-keys: |
${{ runner.os }}-cargo-ci-${{ hashFiles('native/**/Cargo.lock', 'native/**/Cargo.toml') }}-

- name: Test the delta-off error path
run: |
cd native
# The test binary links JNI; libjvm.so must be resolvable at load
# time (same as .github/actions/rust-test).
export LD_LIBRARY_PATH=${JAVA_HOME}/lib/server:${LD_LIBRARY_PATH}
cargo test -p datafusion-comet --no-default-features --features hdfs-opendal delta_scan

# The contrib's dev tooling (benchmark and regression-harness scripts) is
# Python; keep it import-clean on one supported interpreter.
dev-scripts-python:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: Delta dev scripts (Python)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7

- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Byte-compile contrib dev scripts
run: |
python -m compileall -q contrib/delta-spark/dev
66 changes: 66 additions & 0 deletions contrib/delta-spark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Comet Delta Lake Contrib (experimental)

Native Delta Lake reads for Comet. Delta tables are scanned through Comet's
existing native Parquet reader, so they get row-group pruning, page-index
pruning, and filter pushdown, with deletion vectors applied inside the scan.

Support is experimental and explicitly opt-in. Two things are required:

1. This module's jar (`comet-contrib-delta-spark`) on the classpath, alongside
`delta-spark`. It is never bundled into `comet-spark`; without it, Comet
has no Delta surface at all.
2. `spark.comet.scan.delta.enabled=true`. The default is `false`, so the jar
alone does nothing.

Unsupported tables and features fall back to Spark's reader. See the
[user guide](https://datafusion.apache.org/comet/user-guide/latest/delta.html)
for configuration details.

## Supported versions

| Spark | Delta | Status |
| ----- | -------------- | --------------------------------------------- |
| 3.5 | 3.3.x | supported |
| 4.0 | 4.0.x | supported |
| 4.1 | 4.3.x | supported |
| 3.4 | delta-core 2.4 | not supported (older Delta, would need shims) |
| 4.2 | none released | inert until Delta ships a Spark 4.2 release |

## Building and testing

The module builds under the `delta` Maven profile. It resolves `comet-spark`
from the local Maven repository, so install `common` and `spark` from the same
checkout immediately before, as CI does, with the `delta` profile active so that
install produces the spark test-jar the contrib suites depend on; a stale sibling
install is the trap the contributor guide warns about:

```shell
./mvnw -Pspark-3.5,delta install -pl common,spark -DskipTests
./mvnw -Pspark-3.5,delta install -pl contrib/delta-spark
```

Run the test suites the same way (`test` instead of `install` on the second
line). CI runs them
on Spark 3.5, 4.0, and 4.1 via `.github/workflows/delta_contrib_test.yml`.

`dev/` contains a benchmark script (`bench_delta_comet.py`) and a harness for
running Delta's own test suites against Comet (`run-delta-regression.sh`).
Loading