lode/adapters/postgres

A PostgreSQL adapter built on pog (the Gleam client wrapping Erlang pgo).

The adapter is thin: it renders a Query to parameterized SQL via lode/query/sql, converts our Value params to pog values, runs the query through pog, and decodes rows back into Dict(String, Value).

IMPORTANT: start the pog connection with pog.rows_as_map(config, True) so rows come back as column-keyed maps — the row decoder relies on it.

let assert Ok(started) = pog.default_config(process.new_name(“db”)) |> pog.host(“localhost”) |> pog.database(“my_db”) |> pog.rows_as_map(True) |> pog.start let repo = repo.new(postgres.new(started.data))

KNOWN LIMITATION (v0.1): transaction opens a real BEGIN/COMMIT, but repo operations called inside the body still run on the pool connection, not the transaction’s checked-out connection. Single-statement round-trips are correct; multi-statement atomicity needs connection-context threading through the Adapter (planned).

Values

pub fn new(conn: pog.Connection) -> adapter.Adapter

Build an adapter over an already-started pog connection (started with rows_as_map(True)).

Installs a lossless numeric decoder on the connection’s type table (so high-precision decimal columns round-trip without float rounding on read). This is best-effort — if it can’t be installed the adapter still works, with numeric reads bounded by float precision.

pub fn with_connection(
  repo r: repo.Repo,
  body body: fn(pog.Connection) -> a,
) -> a

Run body with the repo’s raw pog.Connection — the escape hatch for engine-specific code the value layer cannot express: compiled query functions (squirrel), COPY, advisory locks. On the base repo this is the pooled connection (pog checks out per statement, so no exclusivity is implied — unlike the SQLite twin); on a transaction-scoped repo it is the transaction’s own connection, so body’s statements join the transaction and roll back with it.

Panics when the repo’s adapter is not this module’s — the connection type would be a lie.

Search Document