Skip to content

feat: add execute_sql_cached binding to CachingReader - #14

Merged
cpsievert merged 3 commits into
mainfrom
feat/caching-reader-execute-sql-cached
Oct 14, 2026
Merged

cpsievert merged 3 commits into
mainfrom
feat/caching-reader-execute-sql-cached

Conversation

@cpsievert

Copy link
Copy Markdown
Collaborator

Summary

Adds an execute_sql_cached(sql) binding to PyCachingReader, exposing the Rust CachingReader's compute surface (available since ggsql 0.5.2) to Python.

Why: CachingReader runs all ggsql-generated derived SQL on a private in-memory DuckDB "cache" connection, while base reads go to the primary data source. Any per-connection setup that derived SQL depends on must therefore happen on the cache connection — most immediately INSTALL spatial; LOAD spatial, which the spatial geom requires. Routing such statements through execute_sql sends them to the primary instead, where locked-down connections (e.g. querychat's filesystem-disabled data sources) reject them, and where they take no effect on the cache even when they succeed.

This unblocks querychat's opt-in "maps" capability, which prewarms the DuckDB spatial extension on the compute surface at app startup (posit-dev/querychat#323). Keeping this as a generic "run SQL on the cache" escape hatch (rather than a spatial-specific method) mirrors the existing Rust API and leaves policy — what to install, when, and how to handle failure — with the caller.

No new dependency requirements: execute_sql_cached has been part of the ggsql crate since 0.5.2, so this builds against the currently pinned version.

Verification

import ggsql

reader = ggsql.CachingReader("duckdb://memory")

# Runs on the private cache connection, never the primary
reader.execute_sql_cached("INSTALL spatial")
reader.execute_sql_cached("LOAD spatial")

spec = reader.execute("VISUALISE FROM ggsql:world DRAW spatial FILTER iso_a3 = 'FRA'")

New tests in TestCachingReader assert that execute_sql_cached executes without touching the primary (primary.calls == 0) and that errors propagate as ValueError. Full suite: 141 passed locally against crates.io ggsql 0.5.2.

Exposes the Rust CachingReader's compute surface (execute_sql_cached,
present since ggsql 0.5.2) to Python.

Setup statements that ggsql's derived SQL depends on must run on the
private cache connection where that SQL executes — e.g. INSTALL/LOAD of
DuckDB extensions such as spatial. Routing them through execute_sql
sends them to the primary instead, where locked-down connections reject
them and they take no effect on the cache.

This is needed by querychat's opt-in "maps" capability to prewarm the
DuckDB spatial extension on the compute surface
(posit-dev/querychat#323).
cpsievert added a commit to posit-dev/querychat that referenced this pull request Oct 14, 2026
prewarm_spatial routed INSTALL/LOAD spatial through execute(), which
targets the user's primary data source. Those connections are typically
locked down (filesystem access disabled), so the install failed and the
"maps" capability was silently disabled — and even where it succeeded it
would take no effect on the connection that matters.

Spatial SQL actually executes on the CachingReader's private in-memory
cache connection (the compute surface), so install/load the extension
there via the new ggsql.CachingReader.execute_sql_cached binding
(posit-dev/ggsql-python#14) and keep the smoke query on execute(), where
it exercises the full spatial path: extension load, builtin ggsql:world
registration, spatial layer execution.

Without a ggsql build that has execute_sql_cached, prewarm fails with a
warning and maps stay unavailable, so this degrades gracefully.
@cpsievert
cpsievert marked this pull request as ready for review October 14, 2026 15:37
@cpsievert
cpsievert merged commit 6d4859f into main Oct 14, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant