Liking cljdoc? Tell your friends :D

datahike.pg.server

PostgreSQL wire protocol server for Datahike.

Starts a pgwire-compatible server that accepts SQL queries from standard PostgreSQL clients (psql, DBeaver, JDBC, Python/psycopg2, etc.) and translates them to Datahike Datalog queries.

Usage: (require '[datahike.api :as d]) (require '[datahike.pg.server :as pg])

(def conn (d/connect cfg)) (def server (pg/start-server conn {:port 5432})) ;; ... use any PostgreSQL client ... (pg/stop-server server)

PostgreSQL wire protocol server for Datahike.

Starts a pgwire-compatible server that accepts SQL queries from standard
PostgreSQL clients (psql, DBeaver, JDBC, Python/psycopg2, etc.) and
translates them to Datahike Datalog queries.

Usage:
  (require '[datahike.api :as d])
  (require '[datahike.pg.server :as pg])

  (def conn (d/connect cfg))
  (def server (pg/start-server conn {:port 5432}))
  ;; ... use any PostgreSQL client ...
  (pg/stop-server server)
raw docstring

*max-result-rows*clj

Maximum rows a SELECT may return before it fails with SQLSTATE 54000. Dynamically bound per handler so every result-formatting path, including set operations and the compiled prepared-statement lane, shares one guard.

Maximum rows a SELECT may return before it fails with SQLSTATE 54000.
Dynamically bound per handler so every result-formatting path, including
set operations and the compiled prepared-statement lane, shares one guard.
sourceraw docstring

*schema-cache-enabled?*clj

Bind false to bypass the cache. For perf comparisons only; production code should leave this on.

Bind false to bypass the cache. For perf comparisons only;
production code should leave this on.
sourceraw docstring

*statement-catalog-basis*clj

source

add-database!clj

(add-database! server-result name conn)

Add a Datahike conn to a running pg-datahike server's registry under name. Subsequent client connections with database=name will route to it. Returns the new registry contents.

Symmetric with the SQL CREATE DATABASE path: add-database! is the Clojure-side knob, :on-create-database is the SQL-side knob, and they share the same atom so either source is visible to both.

Add a Datahike conn to a running pg-datahike server's registry under
`name`. Subsequent client connections with `database=name` will
route to it. Returns the new registry contents.

Symmetric with the SQL `CREATE DATABASE` path: `add-database!` is
the Clojure-side knob, `:on-create-database` is the SQL-side
knob, and they share the same atom so either source is visible
to both.
sourceraw docstring

cache-statsclj

Hit/miss counter for the schema cache. Atom whose identity is stable across reloads so external observers can hold a reference and watch counts. Mutated by every schema-cached call; read for inspection / verification harnesses.

Hit/miss counter for the schema cache. Atom whose
identity is stable across reloads so external observers can hold
a reference and watch counts. Mutated by every `schema-cached`
call; read for inspection / verification harnesses.
sourceraw docstring

databasesclj

(databases server-result)

Return the current set of database names registered with the server.

Return the current set of database names registered with the server.
sourceraw docstring

functions-by-name+arityclj

(functions-by-name+arity db fn-name arity)

Every stored overload of this name with this many arguments. An arity of nil means every overload of the name.

Every stored overload of this name with this many arguments. An
`arity` of nil means every overload of the name.
sourceraw docstring

invalidate-schema-cache!clj

(invalidate-schema-cache!)

Clear the per-schema cache. Called from every DDL exec branch. Also clears the enriched-db catalog cache, whose schema-hash key is blind to registry-entity additions (CREATE TYPE/ENUM/DOMAIN) and ALTER typmod changes — see sql/invalidate-catalog-cache!.

Clear the per-schema cache. Called from every DDL exec branch. Also
 clears the enriched-db catalog cache, whose schema-hash key is blind to
 registry-entity additions (CREATE TYPE/ENUM/DOMAIN) and ALTER typmod
changes — see sql/invalidate-catalog-cache!.
sourceraw docstring

make-query-handlerclj

(make-query-handler conn & [opts])

Create a PgWireServer.QueryHandler that dispatches SQL to Datahike.

conn: a Datahike connection opts: optional map with :on-query (fn [sql]) invoked on every SQL string :compat :strict (default) | :permissive — named bundle of features to silently accept, see compat-presets. :silently-accept a set of reject-kinds to swallow on top of the preset. Valid kinds: :grant :revoke :policy :rls :create-extension. These return a synthetic success tag (e.g. "GRANT") instead of SQLSTATE 0A000. :db-name string — the database name this handler represents. Returned by current_database(); defaults to "datahike" when omitted. :registered-databases seq of strings — all database names registered at the server. Surfaced in the virtual pg_database catalog so \l and DatabaseMetaData enumerate the server's tenancy. Typically supplied by start-server with the keys of its registry; omit for single-DB / bare-handler use. :dispatch-stats optional atom; when supplied, the handler bumps :fast-path-count or :full-parse-count on each parse-sql invocation depending on whether catalog/system-query? matched. Used by tests and observability tooling to detect when an upgrade silently demotes a probe to the slow path. :max-result-rows positive integer — maximum rows returned by one SELECT before SQLSTATE 54000 (default 100000). Set false to disable the guard. Safe query shapes push cap+1 into Datahike; every shape is checked before wire encoding.

Supports temporal session variables: SET datahike.as_of = '2024-01-15T00:00:00Z' SET datahike.since = '2024-01-01T00:00:00Z' SET datahike.history = 'true' RESET datahike.as_of

Create a PgWireServer.QueryHandler that dispatches SQL to Datahike.

conn: a Datahike connection
opts: optional map with
  :on-query         (fn [sql])  invoked on every SQL string
  :compat           :strict (default) | :permissive — named bundle
                    of features to silently accept, see compat-presets.
  :silently-accept  a set of reject-kinds to swallow on top of the
                    preset. Valid kinds: :grant :revoke :policy :rls
                    :create-extension. These return a synthetic
                    success tag (e.g. "GRANT") instead of SQLSTATE
                    0A000.
  :db-name          string — the database name this handler represents.
                    Returned by `current_database()`; defaults to
                    "datahike" when omitted.
  :registered-databases
                    seq of strings — all database names registered at
                    the server. Surfaced in the virtual `pg_database`
                    catalog so \l and DatabaseMetaData enumerate the
                    server's tenancy. Typically supplied by
                    `start-server` with the keys of its registry;
                    omit for single-DB / bare-handler use.
  :dispatch-stats   optional atom; when supplied, the handler bumps
                    :fast-path-count or :full-parse-count on each
                    parse-sql invocation depending on whether
                    catalog/system-query? matched. Used by tests
                    and observability tooling to detect when an
                    upgrade silently demotes a probe to the slow
                    path.
  :max-result-rows positive integer — maximum rows returned by one SELECT
                    before SQLSTATE 54000 (default 100000). Set false to
                    disable the guard. Safe query shapes push cap+1 into
                    Datahike; every shape is checked before wire encoding.

Supports temporal session variables:
  SET datahike.as_of = '2024-01-15T00:00:00Z'
  SET datahike.since = '2024-01-01T00:00:00Z'
  SET datahike.history = 'true'
  RESET datahike.as_of
sourceraw docstring

make-query-handler-factoryclj

(make-query-handler-factory registry-or-atom & [opts])

Build a QueryHandlerFactory that routes on the StartupMessage's database parameter.

registry: {name → conn} map of database name to Datahike conn. opts: forwarded to make-query-handler (e.g. :on-query, :compat).

Clients that pass database=X land on (registry "X"). An optional :branch suffix — database=X:feature — pins the connection's session-state to the :feature branch from the first query. Both the current_database() reply and the pg_database catalog still report the base name; the branch is a session-state detail.

Unknown base-names get a handler that errors every query with 3D000 invalid_catalog_name — matching PG's behaviour on a non-existent db.

Intended for callers who want to wrap their own PgWireServer (e.g. custom host/port binding); start-server uses it internally.

Build a QueryHandlerFactory that routes on the StartupMessage's
`database` parameter.

registry: {name → conn} map of database name to Datahike conn.
opts:     forwarded to make-query-handler (e.g. :on-query, :compat).

Clients that pass `database=X` land on `(registry "X")`. An optional
`:branch` suffix — `database=X:feature` — pins the connection's
session-state to the `:feature` branch from the first query. Both
the `current_database()` reply and the `pg_database` catalog still
report the base name; the branch is a session-state detail.

Unknown base-names get a handler that errors every query with 3D000
invalid_catalog_name — matching PG's behaviour on a non-existent db.

Intended for callers who want to wrap their own PgWireServer (e.g.
custom host/port binding); `start-server` uses it internally.
sourceraw docstring

nextval!clj

(nextval! conn seq-name)

Atomically advance the named sequence on conn and return the new long. Shared core of SELECT nextval(...) and INSERT-VALUES nextval resolution.

PG semantics: a nextval advance is never rolled back, even by ROLLBACK on the surrounding transaction. We match that by always committing to the live conn, regardless of any session's :in-tx? state.

Atomicity: optimistic CAS-retry. Each iteration reads the current :seq/value, computes the new value, and submits

[[:db/cas seq-eid :__seq__/value curr new]]

to d/transact. Datahike's transactor serialises tx applications per conn, so two concurrent CAS submissions see each other: the first wins, the second's old-val no longer matches the transactor's current value and the CAS raises :transact/cas. We re-read and retry. The loser thread will see the winner's new value, compute the next slot, and commit cleanly.

Why CAS instead of the simpler :db.fn/call pattern: Datahike's writer batches multiple in-flight transactions for a single commit, then writes the SAME :db-after (the batch's final db) into every tx-report in the batch. So reading (:db-after report) to recover the value this call assigned doesn't work — it returns the LAST tx in the batch. CAS sidesteps that: the value we intended is the literal new slot of the op-vec, available without reading :db-after.

Throws ex-info :undefined-sequence if the named sequence does not exist, and :serialization-failure if the contention retry budget is exhausted.

Atomically advance the named sequence on `conn` and return the new
long. Shared core of `SELECT nextval(...)` and INSERT-VALUES nextval
resolution.

PG semantics: a `nextval` advance is never rolled back, even by
ROLLBACK on the surrounding transaction. We match that by always
committing to the live conn, regardless of any session's `:in-tx?`
state.

Atomicity: optimistic CAS-retry. Each iteration reads the current
:__seq__/value, computes the new value, and submits

    [[:db/cas seq-eid :__seq__/value curr new]]

to `d/transact`. Datahike's transactor serialises tx applications
per conn, so two concurrent CAS submissions see each other: the
first wins, the second's old-val no longer matches the
transactor's current value and the CAS raises `:transact/cas`. We
re-read and retry. The loser thread will see the winner's new
value, compute the next slot, and commit cleanly.

Why CAS instead of the simpler `:db.fn/call` pattern: Datahike's
writer batches multiple in-flight transactions for a single
commit, then writes the SAME `:db-after` (the batch's final db)
into every tx-report in the batch. So reading `(:db-after report)`
to recover the value this call assigned doesn't work — it returns
the LAST tx in the batch. CAS sidesteps that: the value we
intended is the literal `new` slot of the op-vec, available
without reading `:db-after`.

Throws ex-info `:undefined-sequence` if the named sequence does
not exist, and `:serialization-failure` if the contention retry
budget is exhausted.
sourceraw docstring

password-authenticatorclj

(password-authenticator f)

Adapt (fn [connection password-chars] -> boolean) to the pgwire PasswordAuthenticator interface. connection contains :user, :database, :remote-address, :tls?, and :startup-parameters.

The password is a mutable char array which is cleared immediately after the callback returns. Do not retain it. Authentication failures must return false rather than exposing a reason to the client.

Adapt `(fn [connection password-chars] -> boolean)` to the pgwire
PasswordAuthenticator interface. `connection` contains `:user`,
`:database`, `:remote-address`, `:tls?`, and `:startup-parameters`.

The password is a mutable char array which is cleared immediately after the
callback returns. Do not retain it. Authentication failures must return
false rather than exposing a reason to the client.
sourceraw docstring

recent-commit-writesclj

Ring of recent commits' write sets: [{:max-tx N :eas #{[e a]…}} …], newest last, capped. Lets the COMMIT conflict check test row-level overlap in O(concurrent writes) instead of scanning the whole database, and only for the transactions that actually committed in our window. Commits that bypass transact-tx-buffer! (COPY batches, direct DDL) leave gaps — the checker detects incomplete coverage and aborts conservatively. ::sequence-only records non-transactional nextval reservations without treating them as ordinary row writes.

Ring of recent commits' write sets: [{:max-tx N :eas #{[e a]…}} …],
newest last, capped. Lets the COMMIT conflict check test row-level
overlap in O(concurrent writes) instead of scanning the whole
database, and only for the transactions that actually committed in
our window. Commits that bypass transact-tx-buffer! (COPY batches,
direct DDL) leave gaps — the checker detects incomplete coverage and
aborts conservatively. ::sequence-only records non-transactional
nextval reservations without treating them as ordinary row writes.
sourceraw docstring

remove-database!clj

(remove-database! server-result name)

Remove a database from a running pg-datahike server's registry. Does NOT release the conn or delete the backing store — that's the operator's call. Returns the new registry contents.

Remove a database from a running pg-datahike server's registry.
Does NOT release the conn or delete the backing store — that's
the operator's call. Returns the new registry contents.
sourceraw docstring

reset-advisory-locks!clj

Clear the advisory-lock registry (a test-fixture helper). Re-exported: the registry itself lives in datahike.pg.locks, which the SQL layer requires to answer a TRANSLATED pg_advisory_lock(…).

Clear the advisory-lock registry (a test-fixture helper). Re-exported:
the registry itself lives in `datahike.pg.locks`, which the SQL layer
requires to answer a TRANSLATED `pg_advisory_lock(…)`.
sourceraw docstring

reset-lock-registry!clj

(reset-lock-registry!)

Clear the server-wide row-lock registry. Intended for test fixtures — in production, locks are released on COMMIT/ROLLBACK/DISCARD ALL and when the handler's TCP connection closes. Do not call this from handler code.

Clear the server-wide row-lock registry. Intended for test fixtures —
in production, locks are released on COMMIT/ROLLBACK/DISCARD ALL and
when the handler's TCP connection closes. Do not call this from
handler code.
sourceraw docstring

ssl-context-from-pkcs12clj

(ssl-context-from-pkcs12 path password)

Load a server SSLContext from a PKCS#12 keystore.

password unlocks both the keystore and its private key. Operators can generate or convert this deployment artefact with keytool or OpenSSL.

Load a server SSLContext from a PKCS#12 keystore.

`password` unlocks both the keystore and its private key. Operators can
generate or convert this deployment artefact with `keytool` or OpenSSL.
sourceraw docstring

start-serverclj

(start-server conn-or-registry
              &
              [{:keys [port host on-query default on-create-database
                       on-delete-database database-template]
                :or {port 5432 host "127.0.0.1" default "datahike"}
                :as opts}])

Start a PostgreSQL wire protocol server for one or more Datahike connections.

conn-or-registry is either:

  • a single Datahike conn (convenience — treated as {"datahike" conn}), or
  • a map {name → conn} of database name to conn. Clients route via the StartupMessage database parameter (e.g. jdbc:postgresql://…/prod lands on the "prod" conn).

Options: :port — Port to listen on (default 5432) :host — Host to bind to (default "127.0.0.1") :users — Small deployment-owned {username password} map. Mutually exclusive with :authenticator. :authenticator — PgWireServer.PasswordAuthenticator or (fn [connection password-chars] -> boolean). :ssl-context — Preconfigured javax.net.ssl.SSLContext. :tls — {:keystore path :keystore-password secret} shorthand for a PKCS#12 server keystore. Mutually exclusive with :ssl-context. :require-tls? — Reject plaintext startup before requesting a password. Automatically true for every non-loopback bind. :on-query — Callback (fn [sql-string]) for logging :max-result-rows — Maximum rows returned by one SELECT before SQLSTATE 54000 (default 100000). Set false to disable the guard. :default — Database name used when conn-or-registry is a bare conn (default "datahike"). Ignored when a map is supplied. :on-create-database — Hook (fn [db-name parsed-options]) -> conn that runs when a SQL client issues CREATE DATABASE name [WITH …]. Without this hook configured, CREATE DATABASE returns SQLSTATE 0A000 (provisioning from SQL is a deployment policy decision, not a default). See datahike.pg.sql.database/db-from-template for the common template-driven helper. :on-delete-database — Hook (fn [db-name conn parsed-options]) that runs on DROP DATABASE name. Should release the conn and delete the backing store. Symmetric with :on-create-database; without it, DROP DATABASE returns 0A000. :database-template — Convenience shorthand: a partial datahike config template that pg-datahike uses to build both :on-create-database and :on-delete-database via db-from-template / db-delete-from-template. The template can interpolate {{name}} in string values (handy for file backends with per-database paths). Mutually composable with the explicit hooks; if both are given, the explicit hook wins.

Returns a map with :server (PgWireServer), :registry-atom (an atom holding the live {name → conn} map — mutated by SQL CREATE/DROP DATABASE and add-database! / remove-database!), :port, :host.

Examples: ;; single DB, no SQL provisioning (def srv (pg/start-server conn {:port 5433}))

;; multi-DB, static (def srv (pg/start-server {"prod" prod-conn "staging" staging-conn} {:port 5432}))

;; SQL CREATE/DROP DATABASE provisioned in-memory (def srv (pg/start-server {} {:port 5432 :database-template {:store {:backend :memory} :schema-flexibility :write}}))

(pg/stop-server srv)

Start a PostgreSQL wire protocol server for one or more Datahike
connections.

`conn-or-registry` is either:
  - a single Datahike conn (convenience — treated as
    `{"datahike" conn}`), or
  - a map `{name → conn}` of database name to conn. Clients route
    via the StartupMessage `database` parameter (e.g.
    `jdbc:postgresql://…/prod` lands on the `"prod"` conn).

Options:
  :port      — Port to listen on (default 5432)
  :host      — Host to bind to (default "127.0.0.1")
  :users     — Small deployment-owned `{username password}` map. Mutually
               exclusive with :authenticator.
  :authenticator
             — PgWireServer.PasswordAuthenticator or
               `(fn [connection password-chars] -> boolean)`.
  :ssl-context
             — Preconfigured javax.net.ssl.SSLContext.
  :tls       — `{:keystore path :keystore-password secret}` shorthand for
               a PKCS#12 server keystore. Mutually exclusive with
               :ssl-context.
  :require-tls?
             — Reject plaintext startup before requesting a password.
               Automatically true for every non-loopback bind.
  :on-query  — Callback (fn [sql-string]) for logging
  :max-result-rows
             — Maximum rows returned by one SELECT before SQLSTATE 54000
               (default 100000). Set false to disable the guard.
  :default   — Database name used when `conn-or-registry` is a bare
               conn (default "datahike"). Ignored when a map is
               supplied.
  :on-create-database
             — Hook (fn [db-name parsed-options]) -> conn that runs
               when a SQL client issues `CREATE DATABASE name [WITH …]`.
               Without this hook configured, `CREATE DATABASE`
               returns SQLSTATE 0A000 (provisioning from SQL is a
               deployment policy decision, not a default). See
               `datahike.pg.sql.database/db-from-template` for the
               common template-driven helper.
  :on-delete-database
             — Hook (fn [db-name conn parsed-options]) that runs on
               `DROP DATABASE name`. Should release the conn and
               delete the backing store. Symmetric with
               `:on-create-database`; without it, DROP DATABASE
               returns 0A000.
  :database-template
             — Convenience shorthand: a partial datahike config
               template that pg-datahike uses to build both
               `:on-create-database` and `:on-delete-database` via
               `db-from-template` / `db-delete-from-template`. The
               template can interpolate `{{name}}` in string values
               (handy for file backends with per-database paths).
               Mutually composable with the explicit hooks; if both
               are given, the explicit hook wins.

Returns a map with :server (PgWireServer), :registry-atom (an atom
holding the live {name → conn} map — mutated by SQL CREATE/DROP
DATABASE and `add-database!` / `remove-database!`), :port, :host.

Examples:
  ;; single DB, no SQL provisioning
  (def srv (pg/start-server conn {:port 5433}))

  ;; multi-DB, static
  (def srv (pg/start-server {"prod" prod-conn
                             "staging" staging-conn}
                            {:port 5432}))

  ;; SQL CREATE/DROP DATABASE provisioned in-memory
  (def srv (pg/start-server {}
             {:port 5432
              :database-template {:store {:backend :memory}
                                  :schema-flexibility :write}}))

  (pg/stop-server srv)
sourceraw docstring

stop-serverclj

(stop-server {:keys [server]})

Stop a running PgWire server.

Stop a running PgWire server.
sourceraw docstring

sync-composites-to-codec!clj

(sync-composites-to-codec! db)

Push every known composite type's ordered field OIDs into PgParamCodec's registry so the binary record codec can encode record_out text as a PG binary record. Cheap (one query); called on CREATE TYPE and lazily when a query's result/params reference a composite OID.

Push every known composite type's ordered field OIDs into PgParamCodec's
registry so the binary record codec can encode `record_out` text as a PG
binary record. Cheap (one query); called on CREATE TYPE and lazily when a
query's result/params reference a composite OID.
sourceraw docstring

table-triggersclj

(table-triggers db table)

Every trigger defined on table, as spec maps with their names.

Every trigger defined on `table`, as spec maps with their names.
sourceraw docstring

users-authenticatorclj

(users-authenticator users)

Build a constant-time password authenticator from {username password}. Intended for small deployment-owned credential maps, not as a user store.

Build a constant-time password authenticator from `{username password}`.
Intended for small deployment-owned credential maps, not as a user store.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close