async_postgres/pg_connection/simple_query

Simple Query Protocol entry points and the cancellation helpers built on top of them.

Contains:

  • checkReady — assertion used by every operation that requires csReady.
  • simpleQuery / simpleExec / ping — text-mode multi-statement and single-statement query/exec via the simple query protocol.
  • cancel / cancelNoWait / invalidateOnTimeout — out-of-band cancel request over a separate socket plus the standard "the wait timed out, poison this connection" recovery path used by every timeout wrapper.
  • checkSessionAttrs — SHOW transaction_read_only probe used by the multi-host failover logic in lifecycle.connect.
  • quoteIdentifier — SQL identifier escaping used by LISTEN/UNLISTEN and other identifier-bearing simple-query call sites.
  • QueryResult helpers (len, columnIndex, rows, items).

Sits between buffer_io/cache (which it consumes) and lifecycle (which depends on checkSessionAttrs and the cancel helpers), so it avoids circular imports.

Re-exported through pg_connection.nim.

Procs

proc bytesToString(data: seq[byte]): string {....raises: [], tags: [], forbids: [].}
proc cancel(conn: PgConnection): Future[void] {....stackTrace: false,
    raises: [Exception, OSError, ValueError, IOError, SslError, LibraryError],
    tags: [RootEffect], forbids: [].}
Send a CancelRequest over a separate connection to abort the running query.
proc cancelNoWait(conn: PgConnection) {....raises: [Exception], tags: [RootEffect],
                                        forbids: [].}
Schedule a best-effort CancelRequest without waiting. For use in timeout handlers.
proc checkReady(conn: PgConnection) {....raises: [PgConnectionError], tags: [],
                                      forbids: [].}
Assert that the connection is in csReady state. Raises PgConnectionError otherwise.
proc checkSessionAttrs(conn: PgConnection; attrs: TargetSessionAttrs): Future[
    bool] {....stackTrace: false, raises: [Exception, ValueError, CatchableError],
            tags: [RootEffect, TimeEffect], forbids: [].}
Check whether a connection matches the desired target_session_attrs. Uses SHOW transaction_read_only to determine server role.
proc columnIndex(qr: QueryResult; name: string): int {....raises: [PgTypeError],
    tags: [], forbids: [].}
Find the index of a column by name in a query result.
proc invalidateOnTimeout(conn: PgConnection; reason: string) {.
    ...raises: [Exception, PgTimeoutError], tags: [RootEffect], forbids: [].}

Timeout recovery for a connection whose last request may have left the protocol out of sync. Schedules a best-effort CancelRequest via cancelNoWait, marks the connection csClosed so it cannot be reused, and raises PgTimeoutError with reason.

Under asyncdispatch this is the only safe recovery path: the inner future keeps running in the background after wait() fires, and may still write to the socket. Reusing the connection would interleave its stale write with a new request and corrupt the protocol stream. chronos cancels the inner future properly, but we still invalidate unconditionally — the server may have processed the request partially and the cached session state (prepared statements, portals, transaction status) is no longer reliable.

proc len(qr: QueryResult): int {.inline, ...raises: [], tags: [], forbids: [].}
Return the number of rows in the query result.
proc ping(conn: PgConnection; timeout = ZeroDuration): Future[void] {....raises: [
    Exception, ValueError, CatchableError, PgConnectionError, SslError,
    ProtocolError, PgQueryError, PgTimeoutError, AsyncTimeoutError],
    tags: [RootEffect, TimeEffect], forbids: [].}
Lightweight health check using an empty simple query. Sends Query("") -> expects EmptyQueryResponse + ReadyForQuery. On timeout, the connection is marked csClosed (protocol out of sync).
proc quoteIdentifier(s: string): string {....raises: [], tags: [], forbids: [].}
Quote a SQL identifier (e.g. table/channel name) with double quotes, escaping embedded quotes.
proc rows(qr: QueryResult): seq[Row] {....raises: [], tags: [], forbids: [].}
Return all rows as lightweight Row views into the flat buffer.
proc simpleExec(conn: PgConnection; sql: string;
                timeout: Duration = ZeroDuration): Future[CommandResult] {.
    ...stackTrace: false, raises: [Exception, ValueError, CatchableError],
    tags: [RootEffect, TimeEffect], forbids: [].}

Execute a side-effect SQL command via the simple query protocol, returning the final command tag.

Lighter than exec for parameter-less commands — one Query message, no Parse/Bind/Describe round trip and no plan cache entry. Intended for session-level commands such as BEGIN, SET, VACUUM, LISTEN, NOTIFY.

The SQL string is sent verbatim (no parameters) — only use trusted input, or quote interpolated identifiers yourself via quoteIdentifier.

Multiple ;-separated statements are accepted, but only the last command tag is returned; use simpleQuery if you need per-statement results. For parameterised writes, prefer exec.

On timeout, the connection is marked csClosed (protocol out of sync).

proc simpleExecImpl(conn: PgConnection; sql: string;
                    timeout: Duration = ZeroDuration): Future[string] {.
    ...stackTrace: false, raises: [Exception, ValueError, PgConnectionError,
                                SslError, ProtocolError, PgQueryError,
                                AsyncTimeoutError, CatchableError],
    tags: [RootEffect, TimeEffect], forbids: [].}
proc simpleQuery(conn: PgConnection; sql: string;
                 timeout: Duration = ZeroDuration): Future[seq[QueryResult]] {.
    ...stackTrace: false, raises: [Exception, ValueError, CatchableError],
    tags: [RootEffect, TimeEffect], forbids: [].}

Execute one or more SQL statements via the simple query protocol.

Returns one QueryResult per statement; supports multiple statements separated by ; in a single round trip — this is the main reason to choose simpleQuery over query.

No parameters are supported (the SQL string is sent verbatim — only use trusted input) and rows are always in the text wire format. No server-side plan cache entry is created.

For single-statement parameterised reads, prefer query; for parameter-less commands without rows, prefer simpleExec.

On timeout, the connection is marked csClosed (protocol out of sync).

proc simpleQueryImpl(conn: PgConnection; sql: string;
                     timeout: Duration = ZeroDuration): Future[seq[QueryResult]] {.
    ...stackTrace: false, raises: [Exception, ValueError, PgConnectionError,
                                SslError, ProtocolError, PgQueryError,
                                AsyncTimeoutError, CatchableError],
    tags: [RootEffect, TimeEffect], forbids: [].}

Iterators

iterator items(qr: QueryResult): Row {....raises: [], tags: [], forbids: [].}
Iterate over all rows in the query result.