Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions async_postgres.nim
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,84 @@
##
## waitFor main()
##
## Choosing a query API
## ====================
## Four parameterised entry points are provided. They differ in how parameters
## are supplied and in the amount of per-call allocation:
##
## 1. `sql"..."` macro — compile-time ``{expr}`` interpolation
## ----------------------------------------------------------------------
## Most readable. ``{expr}`` placeholders are rewritten to ``$1, $2, …`` at
## compile time and the expressions are collected into a ``seq[PgParam]``.
## Works with `query`, `exec`, `pool.query`, `cluster.withReadConnection`, etc.
##
## .. code-block:: nim
## let name = "Alice"
## await conn.query(sql"SELECT id FROM users WHERE name = {name}")
##
## - Pros: concise; compile-time placeholder rewriting; SQL injection-safe.
## - Cons: still allocates a ``seq[PgParam]`` per call; ``{expr}`` must be a
## compile-time-visible expression (not an ``openArray`` spread).
## - Use when: SQL is a literal and ergonomics matter more than zero-alloc.
##
## 2. `query`/`exec` with an explicit ``seq[PgParam]``
## ----------------------------------------------------------------------
## The baseline runtime API. Use when the SQL or the parameter list is
## constructed dynamically (e.g. conditional ``WHERE`` clauses).
##
## .. code-block:: nim
## var params: seq[PgParam]
## params.add name.toPgParam
## params.add age.toPgParam
## await conn.query("SELECT id FROM users WHERE name = $1 AND age > $2", params)
##
## The ``pgParams(a, b, c)`` macro builds a ``seq[PgParam]`` in one call. A
## second overload takes ``seq[PgParamInline]`` — constructed manually as
## ``@[toPgParamInline(a), toPgParamInline(b)]`` — which avoids per-parameter
## heap allocations for scalar types.
##
## 3. `queryDirect`/`execDirect` — zero-allocation macros
## ----------------------------------------------------------------------
## Encodes parameters directly into the connection's send buffer at compile
## time; no intermediate ``seq[PgParam]`` or ``seq[byte]`` is built.
##
## .. code-block:: nim
## let qr = await conn.queryDirect("SELECT name FROM users WHERE id = $1", myId)
##
## - Pros: no per-call allocations for the parameter path; same statement
## cache semantics as `query`.
## - Cons: SQL must be a string literal/compile-time constant; arguments are
## positional (``$1, $2, …``), no ``{expr}`` sugar.
## - Use when: the call site is on a hot path and params are scalars.
##
## 4. `simpleQuery`/`simpleExec` — simple query protocol
## ----------------------------------------------------------------------
## Parameter-less, text-only, single round trip. Allows multiple
## ``;``-separated statements and session-only commands that the extended
## protocol rejects (``SET``, ``LISTEN``, ``VACUUM``, …).
##
## .. code-block:: nim
## discard await conn.simpleExec("SET search_path TO myschema, public")
##
## Quick decision table
## --------------------
## ========================= ===================================================
## Situation Prefer
## ========================= ===================================================
## Literal SQL, readability ``sql"..."`` macro
## Dynamic SQL or params ``query(sql, params)`` / ``exec``
## Hot path, scalar params ``queryDirect`` / ``execDirect``
## ``SET`` / multi-statement ``simpleQuery`` / ``simpleExec``
## ========================= ===================================================
##
## ``sql"..."``, ``query``/``exec``, and ``queryDirect``/``execDirect`` share
## the per-connection prepared-statement cache; ``simpleQuery``/``simpleExec``
## use the simple protocol and are not cached. A ``timeout`` parameter is
## accepted by ``query``/``exec`` and ``simpleExec``; on timeout the
## connection is marked closed because the wire protocol desynchronises.
## ``queryDirect``/``execDirect`` and ``simpleQuery`` currently do not accept
## a timeout.
##
## Modules
## =======
## - `pg_connection <async_postgres/pg_connection.html>`_ — Connection management, DSN parsing, SSL, LISTEN/NOTIFY
Expand Down