Skip to content

Add ADBC reader behind 'adbc' feature#422

Open
jimhester wants to merge 11 commits intoposit-dev:mainfrom
jimhester:pr1-adbc-reader
Open

Add ADBC reader behind 'adbc' feature#422
jimhester wants to merge 11 commits intoposit-dev:mainfrom
jimhester:pr1-adbc-reader

Conversation

@jimhester
Copy link
Copy Markdown

@jimhester jimhester commented May 1, 2026

Adds a generic AdbcReader<D: Driver> to src/reader/, behind a new off-by-default adbc feature. Generic over adbc_core::sync::Driver, so concrete ADBC drivers (Flight SQL, Snowflake, BigQuery, etc.) compose at the call site.

Strategic context and the broader 4-PR plan live at #341 (comment).

Testing

  • Default unit tests (cargo test --features adbc --lib): in-process adbc_datafusion covers routing, conversion, dialect, multi-batch / null / empty-result handling.

  • SQLite ADBC equivalence suite (gated #[ignore]): loads the official Apache Arrow SQLite ADBC driver via ManagedDriver::load_from_name("sqlite", ...) and asserts that AdbcReader<sqlite> matches ggsql's existing SqliteReader on the same query against the same tempfile-backed SQLite database. Run locally with:

    # install dbc via instructions at https://docs.columnar.tech/dbc/
    curl -LsSf https://dbc.columnar.tech/install.sh | sh
    dbc install sqlite
    cargo test --features "adbc sqlite" --lib -- --ignored equivalence

    CI installs both and runs the equivalence suite automatically (see the new step in .github/workflows/build.yaml).

Scope

Rust API only — CLI / Jupyter URI plumbing for ADBC is deferred to its own thread.

adbc is intentionally not added to all-readers here; happy to flip if you'd prefer it included.

Test plan

jimhester added 11 commits May 1, 2026 12:33
New off-by-default 'adbc' feature. Implements ggsql's Reader trait over
any adbc_core::sync::Driver: execute_sql, register, unregister, dialect.
Bridges ADBC's &mut Statement API to Reader's &self via RefCell on the
Connection (same pattern as OdbcReader).

Tests are added in subsequent commits.
adbc_datafusion is added as a dev-dep so unit tests can construct an
in-process AdbcReader without dynamically loading any native driver.

Also enables the workspace `arrow` crate's `ipc` feature when `adbc`
is on, since the reader's IPC roundtrip uses both arrow-56 (workspace)
and arrow-58 (direct) IPC paths.
ggsql's execute pipeline emits CREATE OR REPLACE TEMP TABLE for
layer/stat materialization. adbc_datafusion 0.23 rejects that with
NotImplemented("Temporary tables not supported") and unwraps the
result inside Statement::execute, so the unit-test process panics.
The full pipeline works against drivers that support TEMP TABLE
(DuckDB, Trino, etc.) — see the equivalence-test path for that.
The spike-result note and PR-description draft live in the Netflix
fork's records and in this branch's git history; they don't need to
land in the upstream PR tree. Cleaner diff for review.
Loads the official Apache Arrow SQLite ADBC driver via
`ManagedDriver::load_from_name("sqlite", ...)` (installed by `dbc install
sqlite` to the platform manifest path) and asserts that
`AdbcReader<ManagedDriver>` produces output identical to ggsql's
`SqliteReader` on the same query against the same tempfile-backed SQLite
database.

Three tests cover:

- `equiv_simple_select`: scalar projection (int, text, float)
- `equiv_register_and_query`: register-then-query through the standard
  ADBC bulk-ingest path against a real C driver
- `equiv_nulls`: mixed null + typed values

All `#[ignore]`'d so the default `cargo test` is unchanged. Run with
`cargo test --features "adbc sqlite" -- --ignored equivalence` after
installing the driver.

`register()` now sets `IngestMode::Append` on each batch statement so the
SQLite ADBC driver doesn't try to re-CREATE the table our SQL DDL
already created. DataFusion 0.23 returns `Status::NotFound` from
`set_option(IngestMode, ...)`; that's tolerated and the driver's default
append behavior takes over.

Surfaces one pre-existing divergence: `SqliteReader` types an
exclusively-NULL column as `Utf8` (no values to infer from), while
`AdbcReader` correctly carries through the declared projection type. The
nulls test mixes NULLs with typed values to steer around this.
Adds two cargo test runs to the existing build job:
- `cargo test --features "adbc sqlite" --lib` — exercises the
  adbc_datafusion-backed unit tests
- `cargo test --features "adbc sqlite" --lib -- --ignored equivalence`
  — exercises the SQLite ADBC equivalence suite against the official
  Apache Arrow SQLite ADBC driver, installed via `dbc install sqlite`

The default `cargo test --lib --bins` step is unchanged, so the
existing test surface is untouched. dbc is installed via the official
curl-pipe-sh from dbc.columnar.tech.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant