runner
module wittgenstein_sql_runner.runner
SQLRunner — executes SQL against a PostgreSQL database and returns a result envelope.
Classes
-
SQLRunner — Executes SQL queries against a PostgreSQL database.
wittgenstein_sql_runner.runner.SQLRunner
class SQLRunner(pg_dsn: str, statement_timeout_ms: int | None = None, max_rows: int | None = None, read_only: bool = False)
Executes SQL queries against a PostgreSQL database.
Returns an ExecutionResult with the full DataFrame, a row preview,
and a status string — suitable for direct consumption by agent tools.
One instance per target database is typical. Thread-safe (each call opens and closes its own connection).
Three opt-in guardrails are available, all OFF by default so existing
callers see no behavior change: statement_timeout_ms, max_rows,
and read_only. See __init__ for details.
Parameters
-
pg_dsn : str — psycopg2-compatible DSN, e.g. 'postgresql://user:pass@host:port/dbname'
-
statement_timeout_ms : int | None — opt-in. If set, aborts any query on this connection that runs longer than this many milliseconds (via
SET statement_timeout) instead of hanging forever.None(default) leaves PostgreSQL's own timeout in effect. -
max_rows : int | None — opt-in. If set, fetches at most this many rows from the database via
cursor.fetchmany()instead of pulling the full result set into memory.None(default) preserves the previous behavior of fetching everything. -
read_only : bool — opt-in. If
True, puts the connection into a read-only transaction (conn.set_session(readonly=True)) before running the query, so PostgreSQL itself rejects write statements regardless of the SQL text.False(default) preserves the previous read-write behavior.
Methods
-
execute — Run
sqland return the result wrapped in an ExecutionResult.
wittgenstein_sql_runner.runner.SQLRunner.execute
method SQLRunner.execute(sql: str) → ExecutionResult
Run sql and return the result wrapped in an ExecutionResult.
Parameters
-
sql : str — Any read SQL statement (SELECT / WITH / …). Write statements are not prevented here unless
read_only=Truewas passed to this runner — callers are otherwise responsible for access control.
Returns
-
ExecutionResult — ExecutionResult with status='success' and the DataFrame, or status='error' with the exception message. Guardrail failures (a fired
statement_timeout_ms, aread_onlyviolation) are captured here too — never raised to the caller.