Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -63,6 +63,7 @@ and TPC-H/TPC-DS caches on `main` stale until the next unrelated change.
iceberg_1_11 spark_4_1 sql_hive run-spark-4.1-hive-tests
spark_3_4 run-spark-3.4-tests
spark_3_5 run-spark-3.5-tests
delta_contrib run-delta-tests
spark_4_0 run-spark-4.0-tests
iceberg_1_8 run-iceberg-tests
iceberg_1_9 run-iceberg-tests
Expand Down Expand Up @@ -95,6 +96,7 @@ and TPC-H/TPC-DS caches on `main` stale until the next unrelated change.
| `pr_benchmark_check` | merge group, **or** PR with `run-benchmark-check` | benchmark sources only |
| `docs` | push to main, paths matched | `.asf.yaml`, `docs/**`, `docs.yaml` |
| `spark_3_5` | merge group, **or** PR with `run-spark-3.5-tests` | Spark 3.5 sources |
| `delta_contrib` | merge group, **or** PR with `run-delta-tests` | Delta contrib and native sources |
| `spark_4_1` | PR or merge group, paths matched; the `sql_hive` shards only in the merge group **or** with `run-spark-4.1-hive-tests` | Spark 4.1 sources |
| `spark_3_4` | merge group, **or** PR with `run-spark-3.4-tests` | Spark 3.4 sources |
| `spark_4_0` | merge group, **or** PR with `run-spark-4.0-tests` | Spark 4.0 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 @@ -166,6 +166,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 @@ -274,6 +275,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 @@ -403,6 +413,7 @@ jobs:
- pr_benchmark_check
- 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
226 changes: 226 additions & 0 deletions .github/workflows/delta_contrib_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# 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: Cache Maven dependencies
uses: actions/cache@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: |
./mvnw -B -q -Prelease -Pspark-${{ matrix.profile.spark }} 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

# 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

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

- name: Cache Maven dependencies
uses: actions/cache@v6
with:
path: |
~/.m2/repository
/root/.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 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

# `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
65 changes: 65 additions & 0 deletions contrib/delta-spark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!--
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; a stale sibling install is the trap
the contributor guide warns about:

```shell
./mvnw -Pspark-3.5 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