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

The examples assume a Singers table with SingerId and FirstName columns.

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 SingerId, FirstName FROM Singers WHERE SingerId >= @min", {"min": 1})
        df = cur.fetch_df()  # pandas.DataFrame

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.

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. 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 until rollback().
  • 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("DROP TABLE IF EXISTS Albums")
        cur.execute("CREATE TABLE Albums (Id INT64 NOT NULL) PRIMARY KEY (Id)")
        cur.execute("INSERT INTO Albums (Id) VALUES (1)")
    conn.commit()

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

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.11.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.11.0
File
spanner_adbc-0.11.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
spanner_adbc-0.11.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
spanner_adbc-0.11.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
spanner_adbc-0.11.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
spanner_adbc-0.11.0-py3-none-manylinux_2_35_x86_64.whl Python 3 none Linux glibc 2.35+ x86-64 Details
spanner_adbc-0.11.0-py3-none-manylinux_2_35_aarch64.whl Python 3 none Linux glibc 2.35+ ARM64 Details
spanner_adbc-0.11.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
spanner_adbc-0.11.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.11.0-py3-none-win_arm64.whl

Download URL spanner_adbc-0.11.0-py3-none-win_arm64.whl
Size 5.4 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
19e73a89eb69fd60a86bf6c1e161630392d7686e8642adf1da63a0c4f44652c5
BLAKE2b-256 checksum
How to use checksums
07236e069ac4b4fa700ae750e1e572f5bbf714729c5ae067cce9f6ba52b5fb1c
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.0-py3-none-win_amd64.whl
Size 5.8 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
3e34774fcaf028187521234311b8db08a540efd8ff8d38acaeefcffd9536c9d5
BLAKE2b-256 checksum
How to use checksums
ebe69f80a3c5cee230ccbf3793dff2171e608b691119a6048c6863958e1d01cb
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
4774fc9a24de93295915f48e88711c5e23b811e3c198d829cc65c4a8dc52a371
BLAKE2b-256 checksum
How to use checksums
756a4fbc7bedb56841da497dcb1b8d2a0a49d822303842f28d10c2e66b2da4fd
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
03f9adc8c9377a8e4087e90d72a1a596f0d4e369610e0547733165ac04bcc010
BLAKE2b-256 checksum
How to use checksums
d280c1be0dfd2325ebbc98a5cac4d35a8e1c1b64d988964b2d8682d4520be247
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
ddbee9db4674e237484133c5c04479e88d6265c138c02c2ff32501a2fc05d6c6
BLAKE2b-256 checksum
How to use checksums
fd6775b62c74cf141840059668b939c61bfdc91777a177ea19f428e80c6e6cf8
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
a606a0440d554058b2f914dce8ba1c813afeb1b97b72e8220ae0abcfed3730a3
BLAKE2b-256 checksum
How to use checksums
a6dfc24a95eccb591f8edd5615b9eba6bd30179a03c35b8b6ad057ea5d84f596
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
bf32ea6ac23936b1450825e92719f10a04ce61101c5f56e97c48a26e47912e8a
BLAKE2b-256 checksum
How to use checksums
1bb0f182c06c142cf7406464cf99194ebaab062f93f2997c9ba183cbf8c5a050
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 23, 2026.

Transparency log

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

Download URL spanner_adbc-0.11.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
f2614c18e79380773c7ce2149a3cd427a55b20d19a6ab0aa620123aba3676734
BLAKE2b-256 checksum
How to use checksums
3683f53352fc898ff045f0aba5e65bba34a82513424419bd04136e80825c12f4
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 23, 2026.

Transparency log

Security for spanner-adbc 0.11.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.11.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 23, 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