adbc-spanner
An ADBC (Arrow Database Connectivity) driver for Google Cloud Spanner, written in Rust.
It implements the native Rust adbc_core driver traits on top
of the official google-cloud-spanner preview
client from googleapis/google-cloud-rust. Query
results come back as Apache Arrow record batches, so Spanner data flows into the Arrow ecosystem
(DataFusion, Polars, Flight, …) without a row-by-row copy.
SpannerDriver ──▶ SpannerDatabase ──▶ SpannerConnection ──▶ SpannerStatement
Status
Early but working and tested end-to-end against the Spanner emulator. Supported today:
- Connecting to production Spanner or a Spanner emulator.
- SQL queries (
execute), returned as typed ArrowRecordBatches. - DML (
execute_update), returning the affected-row count, run inside an automatically-retried read/write transaction. get_table_types()connection metadata.
Not yet supported (return NotImplemented): query parameter binding / bulk ingest, manual
multi-statement transactions (the driver is autocommit-only), Substrait, partitioned execution, and
the richer catalog-metadata calls (get_objects, get_table_schema, get_statistics, …).
Shared library (loadable driver)
Besides the Rust crate, this builds a C-ABI shared library that any ADBC driver manager can load
(libadbc_spanner.so on Linux, libadbc_spanner.dylib on macOS, adbc_spanner.dll on Windows). It
exports the standard AdbcSpannerInit entrypoint (plus an AdbcDriverInit fallback).
Prebuilt libraries for Linux (x86-64, aarch64), macOS (Apple Silicon) and Windows (x86-64) are
attached to every CI run and to each tagged release.
To build one yourself: cargo build --release → target/release/libadbc_spanner.so.
Example, loading it from the Python driver manager:
=
Usage
Add the dependency (this crate plus the Arrow crates you consume results with):
[]
= "0.1"
= "0.23"
= "58"
use ;
use ;
use AsArray;
use Int64Type;
use SpannerDriver;
Configuration options
Options are set on the database (via new_database_with_opts or set_option):
| Option | Meaning |
|---|---|
OptionDatabase::Uri / adbc.spanner.database |
The Spanner database path projects/<p>/instances/<i>/databases/<d>. Required. |
adbc.spanner.endpoint |
Explicit gRPC endpoint, e.g. http://localhost:9010 for an emulator. |
adbc.spanner.emulator |
true to connect with anonymous credentials (emulator mode). |
The driver also honours the SPANNER_EMULATOR_HOST environment variable: when set it is used as the
endpoint and anonymous credentials are selected automatically. Against production Spanner,
Application Default Credentials
are used.
Type mapping
| Spanner type | Arrow type |
|---|---|
BOOL |
Boolean |
INT64 |
Int64 |
FLOAT64 |
Float64 |
FLOAT32 |
Float32 |
BYTES |
Binary |
STRING / DATE / TIMESTAMP / NUMERIC / JSON / UUID / INTERVAL / ENUM |
Utf8 |
ARRAY / STRUCT |
Utf8 (JSON-encoded) |
NULLs are represented as null slots in the corresponding Arrow array.
Testing
Unit tests run with no external dependencies:
The end-to-end integration test in tests/emulator.rs runs the driver against
the Cloud Spanner emulator. It is skipped
automatically unless SPANNER_EMULATOR_HOST is set, so the command above stays green everywhere.
The helper script starts the emulator in Docker, points the tests at it, and tears it down again:
CI (.github/workflows/ci.yml) runs cargo fmt --check, clippy, and
the full test suite with the emulator as a service container, so the integration test runs on every
push.
Releasing
Releases are cut with cargo-release, configured under
[package.metadata.release] in Cargo.toml.
Prerequisites: cargo install cargo-release, a crates.io token (cargo login), and push access to
main.
Preview a release (dry run — this is the default, nothing is changed):
Perform it:
That single command:
- bumps the version in
Cargo.tomland commits it (Release X.Y.Z), - publishes the crate to crates.io,
- creates the annotated tag
vX.Y.Zand pushes the commit and tag toorigin.
Pushing the vX.Y.Z tag triggers the Shared libraries workflow,
which builds the Linux (x86-64, aarch64), macOS (Apple Silicon) and Windows (x86-64) shared libraries
and attaches them to the GitHub Release for that
tag. So the flow is: cargo release … --execute → crates.io publish + tag → CI attaches the prebuilt
libraries to the release.
License
Licensed under the Apache License, Version 2.0.