Spanner#

Google Cloud Spanner adapter using the Spanner client library with sync and async session pool management.

Request And Session Controls#

Spanner request behavior stays on the existing execution APIs. SQLSpec does not expose public execute_with_options(), execute_partitioned_dml(), apply_mutations(), or provide_batch_snapshot() methods.

Default request controls can be configured through SpannerSyncConfig.driver_features or SpannerAsyncConfig.driver_features:

request_options

Forwarded to Spanner execute_sql(), execute_update(), and batch_update() calls. Use this for request tags, transaction tags, and priority options supported by the Google Cloud Spanner client.

directed_read_options

Forwarded only to read calls that use execute_sql(). Directed reads are not forwarded to DML calls.

retry and timeout

Forwarded to Spanner statement execution calls when provided.

query_options

Forwarded to execute_sql() and execute_update(). Batch DML does not accept query options.

Per-call overrides use the existing execute(), execute_many(), and execute_script() methods:

result = driver.execute(
    "SELECT id FROM users WHERE id = @id",
    id="u-1",
    request_options={"request_tag": "users.lookup"},
    directed_read_options=directed_read_options,
    timeout=10.0,
)

directed_read_options only applies to read statements. The driver accepts the argument for a DML statement so call sites can share option plumbing, but it does not forward directed-read options to execute_update() or batch_update().

Pass last_statement=True to mark the final DML request in a transaction. For scripts, SQLSpec forwards it only when the final statement is DML. This option does not commit the transaction; commit through the normal transaction context or driver API.

Session-Scoped Controls#

SpannerSyncConfig.provide_session() and SpannerAsyncConfig.provide_session() also accept explicit Spanner controls for the returned session context:

with config.provide_session(
    request_options={"transaction_tag": "orders.write"},
    retry=retry,
    timeout=20.0,
) as driver:
    driver.execute("UPDATE orders SET status = @status WHERE id = @id", status="paid", id="o-1")

async with async_config.provide_session(
    request_options={"transaction_tag": "orders.write"},
    retry=retry,
    timeout=20.0,
) as driver:
    await driver.execute("UPDATE orders SET status = @status WHERE id = @id", status="paid", id="o-1")

The explicit provide_session() arguments are copied into the returned driver's feature set and do not mutate config.driver_features.

provide_read_session() is the read-only helper for single-use snapshot reads. For DDL, DML, and write-capable transactions, use provide_session() or provide_write_session().

For read-write transactions with automatic Aborted retry semantics, use run_in_transaction() on either configuration or driver:

async def transfer(driver: SpannerAsyncDriver, amount: int) -> None:
    await driver.execute(
        "UPDATE accounts SET balance = balance - @amount WHERE id = @id",
        amount=amount,
        id="a-1",
    )

await async_config.run_in_transaction(
    transfer,
    100,
    transaction_tag="accounts.transfer",
)

Native Execution Controls#

query_options can be configured on the driver, supplied when opening a session, or overridden per call. They apply to queries and single DML operations; native batch DML does not accept them. last_statement=True marks final transaction DML, including only the final statement of a script.

Opt-in Arrow Batch Write ingestion works from database-backed read sessions. Mutation groups commit independently. Arrow overwrite retains transactional delete-and-insert behavior without partitioned DML or Batch Write.

Schema Changes And Migrations#

DDL statements (CREATE, ALTER, DROP, GRANT, REVOKE, RENAME, and ANALYZE) run through the database update_ddl schema API instead of the session transaction. They run from write sessions; read sessions reject them as they reject DML. Work the write transaction has already begun is committed before the schema change, the way DDL implicitly commits on MySQL or Oracle. Consecutive DDL statements in a script are applied as one schema change.

A write session keeps working after commit() or rollback(): the next statement runs in a new transaction on the same session.

SQL and Python migrations run on both adapters. Spanner schema changes are not transactional, so a failed migration can leave its earlier statements applied. Every table needs a primary key, so write migration DDL in Spanner form:

-- name: migrate-0001-up
CREATE TABLE users (
    id INT64 NOT NULL,
    name STRING(255) NOT NULL
) PRIMARY KEY (id);

-- name: migrate-0001-down
DROP TABLE IF EXISTS users;

Parameter Types#

Both adapters bind datetime.timedelta parameters as Spanner INTERVAL values, including arrays with null elements. Conversion preserves days and microseconds without rounding through floating-point seconds.

Sync Configuration#

With google-cloud-spanner==3.71.0, closing a database that used multiplexed sessions can wait up to ten minutes for the SDK's maintenance thread. The upstream shutdown fix is merged but has not yet been released. Allow for this delay during application shutdown until a fixed SDK is available.

class sqlspec.adapters.spanner.SpannerSyncConfig[source]#

Bases: SyncDatabaseConfig[SpannerSyncConnection, AbstractSessionPool, SpannerSyncDriver]

Spanner configuration and session management.

driver_type#

alias of SpannerSyncDriver

connection_type#

alias of Any

__init__(*, connection_config=None, connection_instance=None, migration_config=None, statement_config=None, driver_features=None, bind_key=None, extension_config=None, observability_config=None, **kwargs)[source]#
get_database()[source]#

Return the configured database, creating the pool and client on first use.

Return type:

Database

Returns:

The Spanner database bound to the configured session pool.

Raises:

ImproperConfigurationError -- If instance_id or database_id is missing.

create_connection()[source]#

Return a read-only snapshot checkout owned by the caller.

The checkout borrows a pooled session when entered and returns it on exit.

Return type:

Any

Returns:

A snapshot checkout to be used as a context manager.

provide_connection(*args, transaction=True, **kwargs)[source]#

Yield a Transaction (default) or Snapshot context from the configured pool.

Parameters:
  • *args (Any) -- Additional positional arguments (unused, for interface compatibility).

  • transaction (bool) -- If True (default), yields a Transaction context that supports execute_update() for DML statements. If False, yields a read-only Snapshot context for SELECT queries.

  • **kwargs (Any) -- Additional keyword arguments (unused, for interface compatibility).

Return type:

SpannerSyncConnectionContext

Returns:

A Spanner connection context manager.

provide_session(*args, statement_config=None, transaction=True, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide a Spanner driver session context manager.

Returns a write-capable Transaction session by default. Pass transaction=False or use provide_read_session() to obtain a read-only Snapshot session.

Parameters:
  • *args -- Additional arguments.

  • statement_config -- Optional statement configuration override.

  • transaction -- Whether to use a Transaction (True, default) or Snapshot (False).

  • request_options -- Session-scoped RequestOptions for Spanner statements.

  • directed_read_options -- Session-scoped DirectedReadOptions for reads.

  • query_options -- Session-scoped QueryOptions for Spanner statements.

  • retry -- Session-scoped retry policy for Spanner statement calls.

  • timeout -- Session-scoped timeout for Spanner statement calls.

  • **kwargs -- Additional keyword arguments.

Returns:

A Spanner driver session context manager.

provide_write_session(*args, statement_config=None, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide a write-capable Spanner session (alias for provide_session()).

provide_read_session(*args, statement_config=None, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide a read-only Snapshot Spanner session.

Use for query workloads that benefit from Spanner's snapshot reads. For DDL/DML, use provide_session() (write-capable by default).

run_in_transaction(fn, *args, **kwargs)[source]#

Execute a callable inside Spanner's retryable transaction runner.

fn is called as fn(driver, *args, **kwargs) with a driver bound to the runner's transaction. A DeadlockError caused by google.api_core.exceptions.Aborted is unwrapped so the runner retries, and a terminal Aborted is raised as DeadlockError.

execute_partitioned_dml(sql, params=None, param_types=None, **kwargs)[source]#

Execute a Partitioned DML statement against the configured Spanner database.

Return type:

int

get_signature_namespace()[source]#

Get the signature namespace for SpannerSyncConfig types.

Return type:

dict[str, typing.Any]

Returns:

Dictionary mapping type names to types.

get_event_runtime_hints()[source]#

Return queue defaults for Spanner JSON and transaction handling.

Return type:

EventRuntimeHints

Async Configuration#

An async write session commits on successful context exit and rolls back on an exception. If you explicitly call await driver.commit() or await driver.rollback(), context exit preserves that completed transaction.

class sqlspec.adapters.spanner.SpannerAsyncConfig[source]#

Bases: AsyncDatabaseConfig[SpannerAsyncConnection, AsyncAbstractSessionPool, SpannerAsyncDriver]

Async Spanner configuration and session management.

driver_type#

alias of SpannerAsyncDriver

connection_type#

alias of Any

__init__(*, connection_config=None, connection_instance=None, migration_config=None, statement_config=None, driver_features=None, bind_key=None, extension_config=None, observability_config=None, **kwargs)[source]#
async get_database()[source]#

Return the configured database, creating the pool and client on first use.

Return type:

Database

Returns:

The async Spanner database bound to the configured session pool.

Raises:

ImproperConfigurationError -- If instance_id or database_id is missing.

async create_connection()[source]#

Return a read-only async snapshot checkout owned by the caller.

The checkout borrows a pooled session when entered and returns it on exit.

Return type:

Any

Returns:

A snapshot checkout to be used as an async context manager.

provide_connection(*args, transaction=True, **kwargs)[source]#

Yield a Transaction (default) or Snapshot context from the configured pool.

Parameters:
  • *args (Any) -- Additional positional arguments (unused, for interface compatibility).

  • transaction (bool) -- If True (default), yields a Transaction context that supports execute_update() for DML statements. If False, yields a read-only Snapshot context for SELECT queries.

  • **kwargs (Any) -- Additional keyword arguments (unused, for interface compatibility).

Return type:

SpannerAsyncConnectionContext

Returns:

An async Spanner connection context manager.

provide_session(*args, statement_config=None, transaction=True, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide an async Spanner driver session context manager.

Returns a write-capable Transaction session by default. Pass transaction=False or use provide_read_session() to obtain a read-only Snapshot session.

Parameters:
  • *args -- Additional arguments.

  • statement_config -- Optional statement configuration override.

  • transaction -- Whether to use a Transaction (True, default) or Snapshot (False).

  • request_options -- Session-scoped RequestOptions for Spanner statements.

  • directed_read_options -- Session-scoped DirectedReadOptions for reads.

  • query_options -- Session-scoped QueryOptions for Spanner statements.

  • retry -- Session-scoped retry policy for Spanner statement calls.

  • timeout -- Session-scoped timeout for Spanner statement calls.

  • **kwargs -- Additional keyword arguments.

Returns:

An async Spanner driver session context manager.

provide_write_session(*args, statement_config=None, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide a write-capable async Spanner session (alias for provide_session()).

provide_read_session(*args, statement_config=None, request_options=None, directed_read_options=None, query_options=None, retry=None, timeout=None, **kwargs)[source]#

Provide a read-only Snapshot async Spanner session.

Use for query workloads that benefit from Spanner's snapshot reads. For DDL/DML, use provide_session() (write-capable by default).

async run_in_transaction(fn, *args, **kwargs)[source]#

Execute a coroutine function inside Spanner's async retryable transaction runner.

fn is awaited as fn(driver, *args, **kwargs) with a driver bound to the runner's transaction. A DeadlockError caused by google.api_core.exceptions.Aborted is unwrapped so the runner retries, and a terminal Aborted is raised as DeadlockError.

async execute_partitioned_dml(sql, params=None, param_types=None, **kwargs)[source]#

Execute a Partitioned DML statement against the configured async Spanner database.

Return type:

int

get_signature_namespace()[source]#

Get the signature namespace for SpannerAsyncConfig types.

Return type:

dict[str, typing.Any]

Returns:

Dictionary mapping type names to types.

get_event_runtime_hints()[source]#

Return queue defaults for Spanner JSON and transaction handling.

Return type:

EventRuntimeHints

Connection Parameters#

class sqlspec.adapters.spanner.SpannerConnectionParams[source]#

Bases: TypedDict

Spanner connection parameters.

Pool Parameters#

class sqlspec.adapters.spanner.SpannerPoolParams[source]#

Bases: SpannerConnectionParams

Session pool configuration.

pool_type must be a sync pool class for SpannerSyncConfig (default FixedSizePool) and an async pool class for SpannerAsyncConfig (default async FixedSizePool).

Driver Features#

class sqlspec.adapters.spanner.SpannerDriverFeatures[source]#

Bases: TypedDict

Driver feature flags for Spanner.

enable_uuid_conversion#

Enable automatic UUID string conversion.

json_serializer#

Custom JSON serializer for parameter conversion.

json_deserializer#

Custom JSON deserializer for result conversion.

retry#

Per-request retry policy passed to execute_sql(), execute_update(), and batch_update().

timeout#

Per-request timeout in seconds passed to execute_sql(), execute_update(), and batch_update().

request_options#

Default RequestOptions forwarded to execute_sql(), execute_update(), and batch_update(). Per-call overrides are available through normal driver execution methods.

directed_read_options#

Default DirectedReadOptions forwarded to execute_sql().

session_labels#

Deprecated compatibility alias for pool session labels. Prefer connection_config["session_labels"].

enable_events#

Enable database event channel support. Defaults to True when extension_config["events"] is configured.

events_backend#

Backend type for event handling. Spanner only supports "poll_queue" (no native pub/sub).

enable_batch_write_api#

Route load_from_arrow through the Spanner Batch Write API (Database.mutation_groups().batch_write()) for high-throughput, independently committed mutation groups instead of a single in-transaction insert_or_update. Defaults to False.

Custom Dialects#

Spanner uses the Spanner and Spangres dialects for SQL compilation. See the Dialects reference for details.

Sync Driver#

class sqlspec.adapters.spanner.SpannerSyncDriver[source]#

Bases: SyncDriverAdapterBase

Synchronous Spanner driver operating on Snapshot or Transaction contexts.

__init__(connection, statement_config=None, driver_features=None)[source]#

Initialize driver adapter with connection and configuration.

Parameters:
  • connection (Any) -- Database connection instance

  • statement_config (StatementConfig | None) -- Statement configuration for the driver

  • driver_features (dict[str, typing.Any] | None) -- Driver-specific features like extensions, secrets, and connection callbacks

  • observability -- Optional runtime handling lifecycle hooks, observers, and spans

property data_dictionary: SpannerSyncDataDictionary#

Get the data dictionary for this driver.

Returns:

Data dictionary instance for metadata queries

dispatch_execute(cursor, statement)[source]#

Execute a single SQL statement.

Must be implemented by each driver for database-specific execution logic.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with execution data

dispatch_select_stream(statement, chunk_size)[source]#

Adapter hook returning a native row stream, or None when unsupported.

Return type:

Optional[SyncRowStream[dict[str, typing.Any]]]

dispatch_execute_many(cursor, statement)[source]#

Execute SQL with multiple parameter sets (executemany).

Must be implemented by each driver for database-specific executemany logic.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with execution data for the many operation

dispatch_execute_script(cursor, statement)[source]#

Execute a SQL script containing multiple statements.

Default implementation splits the script and executes statements individually. Drivers can override for database-specific script execution methods.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with script execution data including statement counts

begin()[source]#

Begin a database transaction on the current connection.

Return type:

None

commit()[source]#

Commit the active transaction when it has work to commit.

Return type:

None

rollback()[source]#

Roll back the active transaction when it has begun.

Return type:

None

create_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

release_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

rollback_to_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

with_cursor(connection)[source]#

Create and return a context manager for cursor acquisition and cleanup.

Returns a context manager that yields a cursor for database operations. Concrete implementations handle database-specific cursor creation and cleanup.

Return type:

SpannerSyncCursor

handle_database_exceptions()[source]#

Handle database-specific exceptions and wrap them appropriately.

Return type:

SpannerSyncExceptionHandler

Returns:

Exception handler with deferred exception pattern for mypyc compatibility. The handler stores mapped exceptions in pending_exception rather than raising from __exit__ to avoid ABI boundary violations.

execute(statement, /, *parameters, statement_config=None, **kwargs)[source]#

Execute a statement with optional Spanner per-call request options.

execute_many(statement, /, parameters, *filters, statement_config=None, **kwargs)[source]#

Execute a batch statement with optional Spanner per-call request options.

execute_script(statement, /, *parameters, statement_config=None, **kwargs)[source]#

Execute a multi-statement script with optional Spanner per-call request options.

select_stream(statement, /, *parameters, schema_type=None, statement_config=None, chunk_size=1000, native_only=False, **kwargs)[source]#

Execute a query and stream rows with optional Spanner per-call options.

select_to_storage(statement, destination, /, *parameters, statement_config=None, partitioner=None, format_hint=None, telemetry=None, **kwargs)[source]#

Execute query and stream Arrow results to storage.

Return type:

StorageBridgeJob

load_from_arrow(table, source, *, partitioner=None, overwrite=False, telemetry=None)[source]#

Load Arrow data into Spanner table via batch mutations.

Return type:

StorageBridgeJob

load_from_storage(table, source, *, file_format, partitioner=None, overwrite=False)[source]#

Load artifacts from storage into Spanner table.

Return type:

StorageBridgeJob

collect_rows(cursor, fetched)[source]#

Collect Spanner rows for the direct execution path.

Dict rows supply their keys as column names; other rows are returned unchanged with no column names.

Return type:

tuple[list[typing.Any], list[str], int]

resolve_rowcount(cursor)[source]#

Resolve rowcount from Spanner cursor for the direct execution path.

Spanner uses execute_update return value, not cursor.rowcount, so this returns 0.

Return type:

int

run_in_transaction(fn, *args, **kwargs)[source]#

Execute a callable inside Spanner's retryable transaction runner.

fn is called as fn(driver, *args, **kwargs) with a driver bound to the runner's transaction. A DeadlockError caused by google.api_core.exceptions.Aborted is unwrapped so the runner retries, and a terminal Aborted is raised as DeadlockError.

execute_partitioned_dml(sql, params=None, param_types=None, **kwargs)[source]#

Execute a Partitioned DML statement against the Spanner database.

Return type:

int

write_insert(table, columns, values)[source]#

Buffer Spanner INSERT mutations on the active transaction or batch.

Return type:

None

write_upsert(table, columns, values)[source]#

Buffer Spanner INSERT_OR_UPDATE mutations on the active transaction or batch.

Return type:

None

write_update(table, columns, values)[source]#

Buffer Spanner UPDATE mutations on the active transaction or batch.

Return type:

None

write_delete(table, keyset)[source]#

Buffer a Spanner DELETE mutation on the active transaction or batch.

Return type:

None

bind_external_transaction()[source]#

Mark the driver as bound to an externally managed transaction runner.

Return type:

None

Async Driver#

class sqlspec.adapters.spanner.SpannerAsyncDriver[source]#

Bases: AsyncDriverAdapterBase

Asynchronous Spanner driver operating on AsyncSnapshot or AsyncTransaction contexts.

__init__(connection, statement_config=None, driver_features=None)[source]#

Initialize driver adapter with connection and configuration.

Parameters:
  • connection (Any) -- Database connection instance

  • statement_config (StatementConfig | None) -- Statement configuration for the driver

  • driver_features (dict[str, typing.Any] | None) -- Driver-specific features like extensions, secrets, and connection callbacks

  • observability -- Optional runtime handling lifecycle hooks, observers, and spans

property data_dictionary: SpannerAsyncDataDictionary#

Get the data dictionary for this driver.

Returns:

Data dictionary instance for metadata queries

async dispatch_execute(cursor, statement)[source]#

Execute a single SQL statement.

Must be implemented by each driver for database-specific execution logic.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with execution data

dispatch_select_stream(statement, chunk_size)[source]#

Adapter hook returning a native row stream, or None when unsupported.

Return type:

Optional[AsyncRowStream[dict[str, typing.Any]]]

async dispatch_execute_many(cursor, statement)[source]#

Execute SQL with multiple parameter sets (executemany).

Must be implemented by each driver for database-specific executemany logic.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with execution data for the many operation

async dispatch_execute_script(cursor, statement)[source]#

Execute a SQL script containing multiple statements.

Default implementation splits the script and executes statements individually. Drivers can override for database-specific script execution methods.

Parameters:
  • cursor (Any) -- Database cursor/connection object

  • statement (SQL) -- SQL statement object with all necessary data and configuration

Return type:

ExecutionResult

Returns:

ExecutionResult with script execution data including statement counts

async begin()[source]#

Begin a database transaction on the current connection.

Return type:

None

async commit()[source]#

Commit the active transaction when it has work to commit.

Return type:

None

async rollback()[source]#

Roll back the active transaction when it has begun.

Return type:

None

async create_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

async release_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

async rollback_to_savepoint(name)[source]#

Raise because Spanner does not support savepoints.

Raises:

NotImplementedError -- Always.

Return type:

None

with_cursor(connection)[source]#

Create and return an async context manager for cursor acquisition and cleanup.

Returns an async context manager that yields a cursor for database operations. Concrete implementations handle database-specific cursor creation and cleanup.

Return type:

SpannerAsyncCursor

handle_database_exceptions()[source]#

Handle database-specific exceptions and wrap them appropriately.

Return type:

SpannerAsyncExceptionHandler

Returns:

Exception handler with deferred exception pattern for mypyc compatibility. The handler stores mapped exceptions in pending_exception rather than raising from __aexit__ to avoid ABI boundary violations.

async execute(statement, /, *parameters, statement_config=None, **kwargs)[source]#

Execute a statement with optional Spanner per-call request options.

async execute_many(statement, /, parameters, *filters, statement_config=None, **kwargs)[source]#

Execute a batch statement with optional Spanner per-call request options.

async execute_script(statement, /, *parameters, statement_config=None, **kwargs)[source]#

Execute a multi-statement script with optional Spanner per-call request options.

select_stream(statement, /, *parameters, schema_type=None, statement_config=None, chunk_size=1000, native_only=False, **kwargs)[source]#

Execute a query and stream rows with optional Spanner per-call options.

async select_to_storage(statement, destination, /, *parameters, statement_config=None, partitioner=None, format_hint=None, telemetry=None, **kwargs)[source]#

Execute query and stream Arrow results to storage asynchronously.

Return type:

StorageBridgeJob

async load_from_arrow(table, source, *, partitioner=None, overwrite=False, telemetry=None)[source]#

Load Arrow data into Spanner table via batch mutations.

Return type:

StorageBridgeJob

async load_from_storage(table, source, *, file_format, partitioner=None, overwrite=False)[source]#

Load artifacts from storage into Spanner table asynchronously.

Return type:

StorageBridgeJob

collect_rows(cursor, fetched)[source]#

Collect Spanner rows for the direct execution path.

Dict rows supply their keys as column names; other rows are returned unchanged with no column names.

Return type:

tuple[list[typing.Any], list[str], int]

resolve_rowcount(cursor)[source]#

Resolve rowcount from Spanner cursor for the direct execution path.

Spanner uses execute_update return value, not cursor.rowcount, so this returns 0.

Return type:

int

async run_in_transaction(fn, *args, **kwargs)[source]#

Execute a coroutine function inside Spanner's async retryable transaction runner.

fn is awaited as fn(driver, *args, **kwargs) with a driver bound to the runner's transaction. A DeadlockError caused by google.api_core.exceptions.Aborted is unwrapped so the runner retries, and a terminal Aborted is raised as DeadlockError.

async execute_partitioned_dml(sql, params=None, param_types=None, **kwargs)[source]#

Execute a Partitioned DML statement against the async Spanner database.

Return type:

int

write_insert(table, columns, values)[source]#

Buffer Spanner INSERT mutations on the active async transaction or batch.

Return type:

None

write_upsert(table, columns, values)[source]#

Buffer Spanner INSERT_OR_UPDATE mutations on the active async transaction or batch.

Return type:

None

write_update(table, columns, values)[source]#

Buffer Spanner UPDATE mutations on the active async transaction or batch.

Return type:

None

write_delete(table, keyset)[source]#

Buffer a Spanner DELETE mutation on the active async transaction or batch.

Return type:

None

bind_external_transaction()[source]#

Mark the driver as bound to an externally managed transaction runner.

Return type:

None

Data Dictionary#

class sqlspec.adapters.spanner.data_dictionary.SpannerSyncDataDictionary[source]#

Bases: SyncDataDictionaryBase

Fetch table, column, and index metadata from Spanner.

dialect: ClassVar[str] = 'spanner'#

Dialect identifier. Must be defined by subclasses as a class attribute.

__init__(mode='googlesql')[source]#
get_query(domain, operation, *, mode=None)[source]#

Return an exact domain query for this dialect.

Return type:

SQL

get_version(driver=None)[source]#

Get Spanner version information.

Parameters:

driver (SpannerSyncDriver | None) -- Spanner driver instance.

Return type:

VersionInfo | None

Returns:

None since Spanner does not expose version information.

get_feature_flag(driver=None, feature='')[source]#

Check if Spanner supports a specific feature.

Parameters:
Return type:

bool

Returns:

True if feature is supported, False otherwise.

get_optimal_type(driver=None, type_category='')[source]#

Get optimal Spanner type for a category.

Parameters:
Return type:

str

Returns:

Spanner-specific type name.

get_tables(driver, schema=None)[source]#

Get tables using INFORMATION_SCHEMA.

Return type:

list[TableMetadata]

get_columns(driver, table=None, schema=None)[source]#

Get column information for a table or schema.

Return type:

list[ColumnMetadata]

get_indexes(driver, table=None, schema=None)[source]#

Get index metadata for a table or schema.

Return type:

list[IndexMetadata]

get_foreign_keys(driver, table=None, schema=None)[source]#

Get foreign key metadata.

Return type:

list[ForeignKeyMetadata]

get_constraints(driver, table=None, schema=None)[source]#

Get constraint metadata for a table or schema.

Return type:

MetadataResult

get_sequences(driver, schema=None, sequence_name=None)[source]#

Get sequence metadata.

Return type:

MetadataResult

get_change_streams(driver, schema=None, stream_name=None)[source]#

Get change stream metadata.

Return type:

MetadataResult

get_system_metadata(driver, request=None, **kwargs)[source]#

Get opt-in Spanner system metadata from SPANNER_SYS.

Return type:

SystemMetadataResult

get_metadata_capabilities(driver, domains=None, *, mode=None)[source]#

Get Spanner data-dictionary capability profile.

Return type:

MetadataCapabilityProfile

get_ddl(driver, object_name, schema=None, *, object_type='table', include_dependencies=True, prefer_native=True, redact=True)[source]#

Get Spanner DDL through the Database Admin API.

Return type:

DDLResult

class sqlspec.adapters.spanner.data_dictionary.SpannerAsyncDataDictionary[source]#

Bases: AsyncDataDictionaryBase

Fetch table, column, and index metadata from Spanner.

dialect: ClassVar[str] = 'spanner'#

Dialect identifier. Must be defined by subclasses as a class attribute.

__init__(mode='googlesql')[source]#
get_query(domain, operation, *, mode=None)[source]#

Return an exact domain query for this dialect.

Return type:

SQL

async get_version(driver=None)[source]#

Get Spanner version information.

Parameters:

driver (SpannerAsyncDriver | None) -- Async Spanner driver instance.

Return type:

VersionInfo | None

Returns:

None since Spanner does not expose version information.

async get_feature_flag(driver=None, feature='')[source]#

Check if Spanner supports a specific feature.

Parameters:
Return type:

bool

Returns:

True if feature is supported, False otherwise.

async get_optimal_type(driver=None, type_category='')[source]#

Get optimal Spanner type for a category.

Parameters:
Return type:

str

Returns:

Spanner-specific type name.

async get_tables(driver, schema=None)[source]#

Get tables using INFORMATION_SCHEMA.

Return type:

list[TableMetadata]

async get_columns(driver, table=None, schema=None)[source]#

Get column information for a table or schema.

Return type:

list[ColumnMetadata]

async get_indexes(driver, table=None, schema=None)[source]#

Get index metadata for a table or schema.

Return type:

list[IndexMetadata]

async get_foreign_keys(driver, table=None, schema=None)[source]#

Get foreign key metadata.

Return type:

list[ForeignKeyMetadata]

async get_constraints(driver, table=None, schema=None)[source]#

Get constraint metadata for a table or schema.

Return type:

MetadataResult

async get_sequences(driver, schema=None, sequence_name=None)[source]#

Get sequence metadata.

Return type:

MetadataResult

async get_change_streams(driver, schema=None, stream_name=None)[source]#

Get change stream metadata.

Return type:

MetadataResult

async get_system_metadata(driver, request=None, **kwargs)[source]#

Get opt-in Spanner system metadata from SPANNER_SYS.

Return type:

SystemMetadataResult

async get_metadata_capabilities(driver, domains=None, *, mode=None)[source]#

Get Spanner data-dictionary capability profile.

Return type:

MetadataCapabilityProfile

async get_ddl(driver, object_name, schema=None, *, object_type='table', include_dependencies=True, prefer_native=True, redact=True)[source]#

Get Spanner DDL through the Database Admin API.

Return type:

DDLResult

Extensions#

class sqlspec.adapters.spanner.adk.SpannerSyncADKStore[source]#

Bases: _SpannerADKStoreMixin, BaseSyncADKStore[SpannerSyncConfig]

Spanner ADK store backed by synchronous Spanner client.

__init__(config)[source]#
create_tables()[source]#

Create tables if they don't exist.

Return type:

None

create_session(session_id, app_name, user_id, state, owner_id=None)[source]#

Create a new session.

Return type:

StoredSession

get_session(app_name, user_id, session_id, *, renew_for=None)[source]#

Get session by ID.

Return type:

StoredSession | None

update_session_state(app_name, user_id, session_id, state)[source]#

Update session state.

Return type:

None

list_sessions(app_name, user_id=None, *, order_by='update_time', descending=True, limit=None, offset=None)[source]#

List sessions for an app.

Return type:

list[StoredSession]

delete_session(app_name, user_id, session_id)[source]#

Delete session and associated events.

Return type:

None

append_event(event_record)[source]#

Append an event to a session.

Return type:

None

append_event_and_update_state(event_record, app_name, user_id, session_id, state, *, app_state=None, user_state=None)[source]#

Atomically append an event and update the session's durable state.

Return type:

StoredSession

get_events(app_name, user_id, session_id, after_timestamp=None, limit=None)[source]#

Get events for a session.

Return type:

list[StoredEvent]

delete_expired_events(before, app_name=None)[source]#

Delete events older than a timestamp, optionally scoped to one application.

Return type:

int

delete_idle_sessions(updated_before, app_name=None)[source]#

Delete sessions older than a timestamp, optionally scoped to one application.

Return type:

int

delete_idle_user_states(updated_before, app_name=None)[source]#

Delete user-scoped state rows older than a timestamp, optionally scoped to one application.

Return type:

int

get_app_state(app_name)[source]#

Return app-scoped state.

Return type:

dict[str, typing.Any] | None

get_user_state(app_name, user_id)[source]#

Return user-scoped state.

Return type:

dict[str, typing.Any] | None

upsert_app_state(app_name, state)[source]#

Insert or replace app-scoped state.

Return type:

None

upsert_user_state(app_name, user_id, state)[source]#

Insert or replace user-scoped state.

Return type:

None

get_metadata(key)[source]#

Return a metadata value.

Return type:

str | None

set_metadata(key, value)[source]#

Set a metadata value.

Return type:

None

class sqlspec.adapters.spanner.adk.SpannerAsyncADKStore[source]#

Bases: _SpannerADKStoreMixin, BaseAsyncADKStore[SpannerAsyncConfig]

Spanner ADK store backed by asynchronous Spanner client.

__init__(config)[source]#
async create_tables()[source]#

Create tables if they don't exist.

Return type:

None

async create_session(session_id, app_name, user_id, state, owner_id=None)[source]#

Create a new session.

Return type:

StoredSession

async get_session(app_name, user_id, session_id, *, renew_for=None)[source]#

Get session by ID.

Return type:

StoredSession | None

async update_session_state(app_name, user_id, session_id, state)[source]#

Update session state.

Return type:

None

async list_sessions(app_name, user_id=None, *, order_by='update_time', descending=True, limit=None, offset=None)[source]#

List sessions for an app.

Return type:

list[StoredSession]

async delete_session(app_name, user_id, session_id)[source]#

Delete session and associated events.

Return type:

None

async append_event(event_record)[source]#

Append an event to a session.

Return type:

None

async append_event_and_update_state(event_record, app_name, user_id, session_id, state, *, app_state=None, user_state=None)[source]#

Atomically append an event and update the session's durable state.

Return type:

StoredSession

async get_events(app_name, user_id, session_id, after_timestamp=None, limit=None)[source]#

Get events for a session.

Return type:

list[StoredEvent]

async delete_expired_events(before, app_name=None)[source]#

Delete events older than a timestamp, optionally scoped to one application.

Return type:

int

async delete_idle_sessions(updated_before, app_name=None)[source]#

Delete sessions older than a timestamp, optionally scoped to one application.

Return type:

int

async delete_idle_user_states(updated_before, app_name=None)[source]#

Delete user-scoped state rows older than a timestamp, optionally scoped to one application.

Return type:

int

async get_app_state(app_name)[source]#

Return app-scoped state.

Return type:

dict[str, typing.Any] | None

async get_user_state(app_name, user_id)[source]#

Return user-scoped state.

Return type:

dict[str, typing.Any] | None

async upsert_app_state(app_name, state)[source]#

Insert or replace app-scoped state.

Return type:

None

async upsert_user_state(app_name, user_id, state)[source]#

Insert or replace user-scoped state.

Return type:

None

async get_metadata(key)[source]#

Return a metadata value.

Return type:

str | None

async set_metadata(key, value)[source]#

Set a metadata value.

Return type:

None

class sqlspec.adapters.spanner.adk.SpannerSyncADKMemoryStore[source]#

Bases: _SpannerADKMemoryStoreMixin, BaseSyncADKMemoryStore[SpannerSyncConfig]

Spanner ADK memory store backed by synchronous Spanner client.

__init__(config)[source]#
create_tables()[source]#

Create tables if they don't exist.

Return type:

None

insert_memory_entries(entries, owner_id=None)[source]#

Bulk insert memory entries with deduplication.

Return type:

int

search_entries(query, app_name, user_id, limit=None, scope_filter='all', embedding=None)[source]#

Search memory entries by text query or vector embedding.

Return type:

list[StoredMemory]

delete_entries_by_session(session_id)[source]#

Delete all memory entries for a specific session.

Return type:

int

delete_entries_older_than(days, app_name=None, scope=None)[source]#

Delete memory entries older than specified days.

Return type:

int

class sqlspec.adapters.spanner.adk.SpannerAsyncADKMemoryStore[source]#

Bases: _SpannerADKMemoryStoreMixin, BaseAsyncADKMemoryStore[SpannerAsyncConfig]

Spanner ADK memory store backed by asynchronous Spanner client.

__init__(config)[source]#
async create_tables()[source]#

Create tables if they don't exist.

Return type:

None

async insert_memory_entries(entries, owner_id=None)[source]#

Bulk insert memory entries with deduplication.

Return type:

int

async search_entries(query, app_name, user_id, limit=None, scope_filter='all', embedding=None)[source]#

Search memory entries by text query or vector embedding.

Return type:

list[StoredMemory]

async delete_entries_by_session(session_id)[source]#

Delete all memory entries for a specific session.

Return type:

int

async delete_entries_older_than(days, app_name=None, scope=None)[source]#

Delete memory entries older than specified days.

Return type:

int

class sqlspec.adapters.spanner.adk.SpannerSyncADKArtifactStore[source]#

Bases: BaseSyncADKArtifactStore[SpannerSyncConfig], _SpannerADKArtifactStoreMixin

Spanner ADK artifact store backed by synchronous Spanner client.

__init__(config)[source]#

Initialize the async ADK artifact store.

Parameters:

config (SpannerSyncConfig) -- SQLSpec database configuration.

create_table()[source]#

Create the artifact versions table if it does not exist.

Return type:

None

drop_table()[source]#

Drop the artifact versions table if it exists.

Return type:

None

insert_artifact(record)[source]#

Insert an artifact version metadata row.

Return type:

None

get_artifact(app_name, user_id, filename, session_id=None, version=None)[source]#

Get a specific artifact version's metadata.

Return type:

StoredArtifact | None

list_artifact_versions(app_name, user_id, filename, session_id=None)[source]#

List all version records for an artifact, ordered by version ascending.

Return type:

list[StoredArtifact]

list_artifact_keys(app_name, user_id, session_id=None)[source]#

List distinct artifact filenames.

Return type:

list[str]

delete_artifact(app_name, user_id, filename, session_id=None)[source]#

Delete all version records for an artifact and return them.

Return type:

list[StoredArtifact]

get_next_version(app_name, user_id, filename, session_id=None)[source]#

Get the next version number for an artifact.

Return type:

int

delete_artifacts_older_than(before, app_name=None)[source]#

Delete artifact version rows created before a cutoff and return them.

Return type:

list[StoredArtifact]

class sqlspec.adapters.spanner.adk.SpannerAsyncADKArtifactStore[source]#

Bases: BaseAsyncADKArtifactStore[SpannerAsyncConfig], _SpannerADKArtifactStoreMixin

Spanner ADK artifact store backed by asynchronous Spanner client.

__init__(config)[source]#

Initialize the async ADK artifact store.

Parameters:

config (SpannerAsyncConfig) -- SQLSpec database configuration.

async create_table()[source]#

Create the artifact versions table if it does not exist.

Return type:

None

async drop_table()[source]#

Drop the artifact versions table if it exists.

Return type:

None

async insert_artifact(record)[source]#

Insert an artifact version metadata row.

Return type:

None

async get_artifact(app_name, user_id, filename, session_id=None, version=None)[source]#

Get a specific artifact version's metadata.

Return type:

StoredArtifact | None

async list_artifact_versions(app_name, user_id, filename, session_id=None)[source]#

List all version records for an artifact, ordered by version ascending.

Return type:

list[StoredArtifact]

async list_artifact_keys(app_name, user_id, session_id=None)[source]#

List distinct artifact filenames.

Return type:

list[str]

async delete_artifact(app_name, user_id, filename, session_id=None)[source]#

Delete all version records for an artifact and return them.

Return type:

list[StoredArtifact]

async get_next_version(app_name, user_id, filename, session_id=None)[source]#

Get the next version number for an artifact.

Return type:

int

async delete_artifacts_older_than(before, app_name=None)[source]#

Delete artifact version rows created before a cutoff and return them.

Return type:

list[StoredArtifact]

class sqlspec.adapters.spanner.litestar.SpannerSyncStore[source]#

Bases: _SpannerLitestarStoreCommonMixin, BaseSQLSpecStore[SpannerSyncConfig]

Spanner-backed Litestar session store using sync driver wrapped as async.

__init__(config)[source]#
async get(key, renew_for=None)[source]#

Get a value.

Parameters:
  • key (str) -- Key associated with the value

  • renew_for (int | timedelta | None) -- If given and the value had an initial expiry time set, renew the expiry time for renew_for seconds. If the value has not been set with an expiry time this is a no-op

Return type:

bytes | None

Returns:

The value associated with key if it exists and is not expired, else None

async set(key, value, expires_in=None)[source]#

Set a value.

Parameters:
  • key (str) -- Key to associate the value with

  • value (str | bytes) -- Value to store

  • expires_in (int | timedelta | None) -- Time in seconds before the key is considered expired

Return type:

None

Returns:

None

async delete(key)[source]#

Delete a value.

If no such key exists, this is a no-op.

Parameters:

key (str) -- Key of the value to delete

Return type:

None

async delete_all()[source]#

Delete all stored values.

Return type:

None

async exists(key)[source]#

Check if a given key exists.

Return type:

bool

async expires_in(key)[source]#

Get the time in seconds key expires in. If no such key exists or no expiry time was set, return None.

Return type:

int | None

async delete_expired()[source]#

Delete all expired sessions.

Return type:

int

Returns:

Number of sessions deleted.

async create_table()[source]#

Create the session table if it doesn't exist.

Return type:

None

class sqlspec.adapters.spanner.litestar.SpannerAsyncStore[source]#

Bases: _SpannerLitestarStoreCommonMixin, BaseSQLSpecStore[SpannerAsyncConfig]

Spanner-backed Litestar session store using native async Spanner client.

__init__(config)[source]#
async get(key, renew_for=None)[source]#

Get a value.

Parameters:
  • key (str) -- Key associated with the value

  • renew_for (int | timedelta | None) -- If given and the value had an initial expiry time set, renew the expiry time for renew_for seconds. If the value has not been set with an expiry time this is a no-op

Return type:

bytes | None

Returns:

The value associated with key if it exists and is not expired, else None

async set(key, value, expires_in=None)[source]#

Set a value.

Parameters:
  • key (str) -- Key to associate the value with

  • value (str | bytes) -- Value to store

  • expires_in (int | timedelta | None) -- Time in seconds before the key is considered expired

Return type:

None

Returns:

None

async delete(key)[source]#

Delete a value.

If no such key exists, this is a no-op.

Parameters:

key (str) -- Key of the value to delete

Return type:

None

async delete_all()[source]#

Delete all stored values.

Return type:

None

async exists(key)[source]#

Check if a given key exists.

Return type:

bool

async expires_in(key)[source]#

Get the time in seconds key expires in. If no such key exists or no expiry time was set, return None.

Return type:

int | None

async delete_expired()[source]#

Delete all expired sessions.

Return type:

int

Returns:

Number of sessions deleted.

async create_table()[source]#

Create the session table if it doesn't exist.

Return type:

None

class sqlspec.adapters.spanner.events.SpannerSyncEventQueueStore[source]#

Bases: _SpannerEventStoreMixin, BaseEventQueueStore[SpannerSyncConfig]

Spanner event queue store for synchronous configs.

Spanner does not support IF NOT EXISTS, so statements must be executed with proper error handling for existing objects.

Parameters:

config (TypeVar(ConfigT, bound= DatabaseConfigProtocol[Any, Any, Any])) -- SpannerSyncConfig with extension_config["events"] settings.

create_table()[source]#

Create the event queue table and index through Database.update_ddl.

Raises:

TypeError -- If the store's config is not a SpannerSyncConfig.

Return type:

None

drop_table()[source]#

Drop the event queue table and index through Database.update_ddl.

Raises:

TypeError -- If the store's config is not a SpannerSyncConfig.

Return type:

None

class sqlspec.adapters.spanner.events.SpannerAsyncEventQueueStore[source]#

Bases: _SpannerEventStoreMixin, BaseEventQueueStore[SpannerAsyncConfig]

Spanner event queue store for asynchronous configs.

Spanner does not support IF NOT EXISTS, so statements must be executed with proper error handling for existing objects.

Parameters:

config (TypeVar(ConfigT, bound= DatabaseConfigProtocol[Any, Any, Any])) -- SpannerAsyncConfig with extension_config["events"] settings.

async create_table()[source]#

Create the event queue table and index through Database.update_ddl.

Raises:

TypeError -- If the store's config is not a SpannerAsyncConfig.

Return type:

None

async drop_table()[source]#

Drop the event queue table and index through Database.update_ddl.

Raises:

TypeError -- If the store's config is not a SpannerAsyncConfig.

Return type:

None

Extension Settings#

Use the configuration types below in their corresponding extension_config namespace: "litestar", "events", or "adk" as supported by this adapter.

class sqlspec.adapters.spanner.litestar.SpannerLitestarConfig[source]#

Bases: LitestarConfig

Spanner-specific Litestar settings.

Use inside extension_config["litestar"] with this adapter's session store.

shard_count: NotRequired[int]#

Number of session key shards.

table_options: NotRequired[str]#

Table DDL options.

index_options: NotRequired[str]#

Index DDL options.

class sqlspec.adapters.spanner.adk.SpannerADKConfig[source]#

Bases: ADKConfig

Spanner-specific ADK extension settings.

shard_count: NotRequired[int]#

Generated shard count for hot key mitigation.

session_table_options: NotRequired[str]#

Raw Spanner OPTIONS clause content for the ADK session table.

events_table_options: NotRequired[str]#

Raw Spanner OPTIONS clause content for the ADK events table.

memory_table_options: NotRequired[str]#

Raw Spanner OPTIONS clause content for the ADK memory table.

expires_index_options: NotRequired[str]#

Raw Spanner OPTIONS clause content for expiration indexes.

retention: NotRequired[SpannerADKRetentionConfig]#

Spanner row-deletion retention policy settings.

vector_dimensions: NotRequired[int | None]#

Optional fixed dimensionality for the memory embedding column.

vector_distance_type: NotRequired[str]#

Distance metric for the memory vector index ('COSINE', 'EUCLIDEAN', 'DOT_PRODUCT').

vector_index_enabled: NotRequired[bool]#

Whether to emit CREATE VECTOR INDEX for the memory table.

scann_tree_depth: NotRequired[int]#

ScaNN tree depth for the memory vector index (2 or 3).

scann_num_leaves: NotRequired[int]#

ScaNN leaf count for the memory vector index.

Enable Reciprocal Rank Fusion when both embedding and FTS query are supplied.

enable_memory_graph: NotRequired[bool]#

Emit CREATE OR REPLACE PROPERTY GRAPH over the ADK memory table.

memory_graph_name: NotRequired[str]#

Name of the Spanner Property Graph created over the ADK memory table.

class sqlspec.adapters.spanner.adk.SpannerADKRetentionConfig[source]#

Bases: TypedDict

Spanner-specific ADK row-deletion policy settings.

session_ttl_seconds: NotRequired[int]#

Session row retention in seconds.

event_ttl_seconds: NotRequired[int]#

Event row retention in seconds.

memory_ttl_seconds: NotRequired[int]#

Memory row retention in seconds.

artifact_ttl_seconds: NotRequired[int]#

Artifact row retention in seconds.