Skip to main content

spanner-adbc

Experimental: this package is AI-generated and has not yet seen real-world use.

PyPI version Python versions Wheel License Build

A Python ADBC driver for Google Cloud Spanner and Spanner Omni. It provides a DBAPI 2.0 interface that returns Apache Arrow data for pandas, Polars, DuckDB or PyArrow. Only GoogleSQL databases are supported, not the PostgreSQL dialect.

Install

Requires Python 3.11 or later and adbc-driver-manager 1.8 or later, which pip installs. Wheels bundle the native driver; see supported platforms.

pip install "spanner-adbc[dbapi]"  # includes PyArrow and pandas

Plain spanner-adbc installs only the low-level ADBC API.

Quickstart

Connect to an existing GoogleSQL database using Application Default Credentials. This query needs no tables:

import spanner_adbc.dbapi as spanner

uri = "spanner:///projects/my-project/instances/my-instance/databases/my-db"
with spanner.connect(uri) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT @name AS name", {"name": "Alice"})
        print(cur.fetch_arrow_table())

Parameters use the GoogleSQL @name syntax, and ? placeholders are rejected. A dict binds parameters by name. A tuple binds them in the order they first appear in the SQL.

The later table examples use this sample table:

CREATE TABLE Singers (
    SingerId INT64 NOT NULL,
    FirstName STRING(MAX)
) PRIMARY KEY (SingerId);
INSERT INTO Singers (SingerId, FirstName) VALUES (1, 'Alice'), (2, 'Bob');

Run the CREATE TABLE and INSERT separately with autocommit=True; the driver doesn't accept DDL and DML in the same call.

Connecting

The driver uses Application Default Credentials unless db_kwargs sets other credentials. The option enums name every key, and raw strings such as "spanner.endpoint" work too:

import spanner_adbc.dbapi as spanner
from spanner_adbc import DatabaseOptions

with spanner.connect(
    "spanner:///projects/p/instances/i/databases/d",
    {DatabaseOptions.KEYFILE: "/path/to/service-account.json"},
) as conn:
    ...

To use the emulator, set SPANNER_EMULATOR_HOST, or set DatabaseOptions.EMULATOR to "true" and DatabaseOptions.ENDPOINT to its host:port. For Spanner Omni, set DatabaseOptions.INSTANCE_TYPE to "omni" and DatabaseOptions.ENDPOINT to the server. Authentication covers the credential options and when the driver connects anonymously.

Connections don't carry over into a forked process. With multiprocessing's fork start method, the default on Linux before Python 3.14, connect in each worker; see forked processes.

Options

connect(uri, db_kwargs, conn_kwargs, *, autocommit=False) takes database and connection options, and conn.cursor(adbc_stmt_kwargs=...) takes statement options. DatabaseOptions, ConnectionOptions and StatementOptions list the keys. They are StrEnums, so members work as dictionary keys, but the typed driver manager getters, such as get_option_int, need .value. Use string values in db_kwargs and conn_kwargs for compatibility with driver manager 1.8. The autocommit keyword overrides ConnectionOptions.AUTOCOMMIT in conn_kwargs. The option reference lists types, defaults and accepted values.

import spanner_adbc.dbapi as spanner
from spanner_adbc import ConnectionOptions, StatementOptions

with spanner.connect(
    "spanner:///projects/p/instances/i/databases/d",
    conn_kwargs={ConnectionOptions.READ_STALENESS: "max:10s"},
    autocommit=True,
) as conn:
    with conn.cursor(adbc_stmt_kwargs={StatementOptions.ROWS_PER_BATCH: "1024"}) as cur:
        cur.execute("SELECT * FROM Singers")

Transactions

Following DBAPI, connections start with autocommit=False. Manual transactions differ from most databases:

  • A transaction runs either queries or writes, whichever comes first. Mixing them raises ProgrammingError until you commit or roll back. Queries share one snapshot, and there is no read-your-writes.
  • DML is buffered and runs at commit(), so errors such as a duplicate key come from commit(), and rowcount is -1. A failed commit keeps the buffered writes. If a commit times out or loses its connection, it may already have applied; use rollback() to discard the buffer before deciding whether to retry the work.
  • Closing the connection, including leaving its with block, discards uncommitted writes.
  • DDL runs immediately, and rollback can't undo it.
  • THEN RETURN and partitioned DML need autocommit=True.
import spanner_adbc.dbapi as spanner

with spanner.connect("spanner:///projects/p/instances/i/databases/d") as conn:
    with conn.cursor() as cur:
        cur.execute("CREATE TABLE AdbcExample (Id INT64 NOT NULL) PRIMARY KEY (Id)")
        cur.execute("INSERT INTO AdbcExample (Id) VALUES (1)")
    conn.commit()

    with conn.cursor() as cur:
        cur.execute("SELECT COUNT(*) FROM AdbcExample")
        assert cur.fetchone() == (1,)
    conn.rollback()  # end the read snapshot

    with conn.cursor() as cur:
        cur.execute("DROP TABLE AdbcExample")

See transactions for the details.

Errors

Errors are the PEP 249 exceptions that adbc_driver_manager.dbapi raises for each ADBC status, also exported by spanner_adbc.dbapi. Errors lists the status for each Spanner error code, and exc.details includes the numeric code as spanner.vendor_code.

DataFrames

fetch_arrow_table() and fetch_df() load the whole result into memory, and fetch_record_batch() streams it while the cursor is open. With Polars 2.0, fetch_polars() returns a struct Series rather than a DataFrame, so use pl.from_arrow(cur.fetch_arrow_table()) or pl.read_database() instead.

import spanner_adbc.dbapi as spanner

with spanner.connect("spanner:///projects/p/instances/i/databases/d") as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT SingerId, FirstName FROM Singers")
        with cur.fetch_record_batch() as reader:
            for batch in reader:
                print(batch.num_rows)

pandas and Polars accept the connection directly:

import pandas as pd
import polars as pl
import spanner_adbc.dbapi as spanner

with spanner.connect("spanner:///projects/p/instances/i/databases/d", autocommit=True) as conn:
    frame = pd.read_sql("SELECT SingerId, FirstName FROM Singers", conn)
    frame.to_sql("SingersCopy", conn, if_exists="append", index=False)

    df = pl.read_database("SELECT SingerId, FirstName FROM Singers", connection=conn)
    df.write_database("SingersCopy", connection=conn, if_table_exists="append")

pandas can't pass params to an ADBC connection, so bind parameters with cur.execute() and cur.fetch_df() instead. pd.read_sql_table() and to_sql(if_exists="replace") fail because pandas quotes table names with ", which GoogleSQL reads as a string. Polars' read_database_uri() doesn't work either, since it looks for a module named adbc_driver_spanner. Both libraries write through bulk ingest, so use autocommit for large writes. In manual mode, end a read with conn.rollback() before writing.

Results follow the type mapping. Polars 2.0 reads JSON columns as Extension('arrow.json', String). Spanner allows duplicate STRUCT field names: pandas and DuckDB keep only the last field of each name, and Polars raises DuplicateError when unnesting such a struct. pyarrow and Polars infer List(Null) for [] and [None], which bind untyped.

DuckDB can query fetched Arrow data in-process:

import duckdb
import spanner_adbc.dbapi as spanner

with spanner.connect("spanner:///projects/p/instances/i/databases/d") as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT SingerId, FirstName FROM Singers")
        singers = cur.fetch_arrow_table()

print(duckdb.sql("SELECT COUNT(*) FROM singers").fetchall())

Bulk ingest

cur.adbc_ingest(table, data, mode=...) inserts Arrow data, or anything that exports the Arrow PyCapsule interface, such as a Polars DataFrame:

import pyarrow as pa
import spanner_adbc.dbapi as spanner

data = pa.table({"SingerId": [10, 11], "FirstName": ["Carol", "Dave"]})

with spanner.connect("spanner:///projects/p/instances/i/databases/d", autocommit=True) as conn:
    with conn.cursor() as cur:
        rows = cur.adbc_ingest("Singers", data, mode="append")

The modes are create (the default), append, create_append and replace. Tables that ingest creates have Spanner's hidden rowid as primary key, so create the table yourself to choose the key.

With autocommit=True, ingest commits in chunks, so a failed load can leave rows behind. In manual mode, ingest returns -1 and the rows apply at commit() in one commit, which Spanner caps at 80,000 mutations: one per cell, plus index entries. Use autocommit for large loads, including pandas' to_sql() and Polars' write_database().

Partitioned reads

adbc_execute_partitions() splits a query into partitions that any connection can read with adbc_read_partition(), in parallel if you like. On Cloud Spanner, set StatementOptions.DATA_BOOST to "true" on the partitioning cursor to read them on Data Boost.

import spanner_adbc.dbapi as spanner

with spanner.connect("spanner:///projects/p/instances/i/databases/d") as conn:
    with conn.cursor() as cur:
        partitions, schema = cur.adbc_execute_partitions("SELECT SingerId FROM Singers")

    for partition in partitions:
        with conn.cursor() as cur:
            cur.adbc_read_partition(partition)
            table = cur.fetch_arrow_table()

Spanner only partitions some queries, such as simple scans; see reading data in parallel. Only read partitions from trusted sources: they aren't authenticated, as the limitations explain.

Loading by name

spanner.connect() loads the bundled library directly. To load the driver by name through adbc_driver_manager 1.9.0 or later, install an ADBC driver manifest:

python -m spanner_adbc.manifest install  # or spanner-adbc-install-manifest
import adbc_driver_manager.dbapi

with adbc_driver_manager.dbapi.connect(
    driver="spanner", uri="spanner:///projects/p/instances/i/databases/d"
) as conn:
    ...

From version 1.11.0, driver can be left out, and the driver manager picks the driver from the URI scheme. The manifest goes in <sys.prefix>/etc/adbc/drivers in a virtual environment and in the user configuration directory otherwise, and python -m spanner_adbc.manifest path prints where. It records the library's absolute path, so install it again after upgrading or moving the environment. Use install --dir to write it into a directory on ADBC_DRIVER_PATH instead.

Supported platforms

Platform Wheel tag
Linux x86-64 and aarch64, glibc 2.35+ manylinux_2_35
Linux x86-64 and aarch64, musl 1.2+ musllinux_1_2
macOS 11+ arm64 macosx_11_0_arm64
macOS 10.15+ x86-64 macosx_10_15_x86_64
Windows x86-64 and arm64 win_amd64, win_arm64

On other systems, build the library and package it yourself. The Python build doesn't compile Rust; it packages the one library staged in python/spanner_adbc/, such as libspanner_adbc.so on Linux:

cargo build --release --features strip-logging
cp target/release/libspanner_adbc.so python/spanner_adbc/
pip install './python[dbapi]'

The release wheels use the strip-logging feature too; without it, the library is larger but behaves the same.

See CONTRIBUTING.md for development and releases.

Metadata

Release files for spanner-adbc 0.12.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for spanner-adbc 0.12.0
File
spanner_adbc-0.12.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
spanner_adbc-0.12.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
spanner_adbc-0.12.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
spanner_adbc-0.12.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
spanner_adbc-0.12.0-py3-none-manylinux_2_35_x86_64.whl Python 3 none Linux glibc 2.35+ x86-64 Details
spanner_adbc-0.12.0-py3-none-manylinux_2_35_aarch64.whl Python 3 none Linux glibc 2.35+ ARM64 Details
spanner_adbc-0.12.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
spanner_adbc-0.12.0-py3-none-macosx_10_15_x86_64.whl Python 3 none macOS 10.15+ x86-64 Details

Total release size: 42.3 MB

Release files / spanner_adbc-0.12.0-py3-none-win_arm64.whl

Download URL spanner_adbc-0.12.0-py3-none-win_arm64.whl
Size 5.4 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
7337e0c00f2b1c63b98136c23ae616e56b52d220df00037fea0f050a7d0dd678
BLAKE2b-256 checksum
How to use checksums
573e31ed9529c9606415833c3d359178b4c2dbac9777c20ff0598484d93d080f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-win_amd64.whl

Download URL spanner_adbc-0.12.0-py3-none-win_amd64.whl
Size 5.8 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
67026a4c36a7a82c7844c19869f591563fcac8f7f96f2fdca772fb30a13c69b6
BLAKE2b-256 checksum
How to use checksums
47eaead180cfd2d5c33a40600d0d71d63fef76ca99091e22c475e838765319c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-musllinux_1_2_x86_64.whl

Download URL spanner_adbc-0.12.0-py3-none-musllinux_1_2_x86_64.whl
Size 5.4 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
33e86f7668b2409a7cd448d7188a069e40e1b0500ca51d202e922acf64b9d409
BLAKE2b-256 checksum
How to use checksums
d5be67ea8adbbd7f9d2ff794809f2f67de3d4bf6b3af3412d9cd21acc7973f00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-musllinux_1_2_aarch64.whl

Download URL spanner_adbc-0.12.0-py3-none-musllinux_1_2_aarch64.whl
Size 5.1 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
ecc34f80807a463ebfe3272cda99f34e1359fd9292dbb3dcce97b70e0bd7fb6e
BLAKE2b-256 checksum
How to use checksums
cb8b256ab77cf395afb07986822178180a0f37a6dbf1a0281a9ca751369cd1ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-manylinux_2_35_x86_64.whl

Download URL spanner_adbc-0.12.0-py3-none-manylinux_2_35_x86_64.whl
Size 5.5 MB
Tags Linux glibc 2.35+ x86-64 Python 3
SHA-256 checksum
How to use checksums
de4817dfe537727f6970f91c8b9e1dc2cad4986f77cfb3ce89493012365b4f8c
BLAKE2b-256 checksum
How to use checksums
4d2c05aee84f8cbcc9a6cded11723cdf781af609228b29d9d313ff5ccabae8d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-manylinux_2_35_aarch64.whl

Download URL spanner_adbc-0.12.0-py3-none-manylinux_2_35_aarch64.whl
Size 5.1 MB
Tags Linux glibc 2.35+ ARM64 Python 3
SHA-256 checksum
How to use checksums
143f3d65f19b21aee1449650b0d0c724022b7738bea6f850766b183b4dbf68a6
BLAKE2b-256 checksum
How to use checksums
719a529d7d9db3431b1c8f4a892116e1d2afd0375fce219426aa1a0c366c5a4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-macosx_11_0_arm64.whl

Download URL spanner_adbc-0.12.0-py3-none-macosx_11_0_arm64.whl
Size 4.9 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e03fb5bfa49aa0d9b8b635c5c90f76cda010cf58f9581f5efb874a332202773d
BLAKE2b-256 checksum
How to use checksums
bf5656ae2251a38512672d3d78288d4cbb4d703adc58c475bf58a70b8c5a6c96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / spanner_adbc-0.12.0-py3-none-macosx_10_15_x86_64.whl

Download URL spanner_adbc-0.12.0-py3-none-macosx_10_15_x86_64.whl
Size 5.2 MB
Tags Python 3 macOS 10.15+ x86-64
SHA-256 checksum
How to use checksums
2ee943d885584fc4d63bae829f6f5fcd7a0e71111ef87cee0c7fd5e6db7e55b8
BLAKE2b-256 checksum
How to use checksums
a1a9b5d829e34d6e0a29e2d2e583f705a79bcee669b4d6f16eceefb7a320fddb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for spanner-adbc 0.12.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for spanner_adbc-0.12.0-py3-none-win_arm64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page