Executing queries against a configured database — platform's data-access API.
The sanctioned surface for every module's persistence layer. Modules used to
require wagoe.platform.shell.adapters.database.common.core instead, which
is platform's shell: 20 sites across tenant, user, admin, workflow and
devtools reaching into another module's internals, carried as the largest
entry in .wagoe/check-ports.edn (BOU-303).
Deliberately narrower than what it delegates to. Connection-pool lifecycle,
raw SQL formatting and adapter construction stay internal — a module needs
to run a query, not to build a pool. wagoe.platform.ports.database is the
other half: what an adapter must implement.
Not a protocol, and that is the point. There is one way to execute a
HoneySQL map against a JDBC connection, and the differences between engines
live behind the DBAdapter port. A second protocol here would name a seam
nothing implements — the mistake ADR-037 removed.
Executing queries against a configured database — platform's data-access API. The sanctioned surface for every module's persistence layer. Modules used to require `wagoe.platform.shell.adapters.database.common.core` instead, which is platform's shell: 20 sites across tenant, user, admin, workflow and devtools reaching into another module's internals, carried as the largest entry in `.wagoe/check-ports.edn` (BOU-303). Deliberately narrower than what it delegates to. Connection-pool lifecycle, raw SQL formatting and adapter construction stay internal — a module needs to run a query, not to build a pool. `wagoe.platform.ports.database` is the other half: what an adapter must implement. Not a protocol, and that is the point. There is one way to execute a HoneySQL map against a JDBC connection, and the differences between engines live behind the `DBAdapter` port. A second protocol here would name a seam nothing implements — the mistake ADR-037 removed.
The tenant whose schema this thread's work runs in, or nil. The tenant module binds it around a tenant request and a tenant job, so code deeper in the call can refuse to fall back to public and can pass the tenant on.
The tenant whose schema this thread's work runs in, or nil. The tenant module binds it around a tenant request and a tenant job, so code deeper in the call can refuse to fall back to public and can pass the tenant on.
The schema the transaction open on this thread is bound to, or nil. The tenant module binds it with the transaction, so a store can check its tables are there without asking the database for its search_path.
The schema the transaction open on this thread is bound to, or nil. The tenant module binds it with the transaction, so a store can check its tables are there without asking the database for its search_path.
Add a column unless it is already there.
Add a column unless it is already there.
Add the columns a table lacks, reading it once.
Add the columns a table lacks, reading it once.
Call f once the transaction with-transaction holds open on this thread
commits, never if it rolls back; with none open, now.
Call `f` once the transaction `with-transaction` holds open on this thread commits, never if it rolls back; with none open, now.
A builder-fn keying x2y_id as :x2y-id, where the default gives :x-2y-id.
Opt in with :builder-fn on the db context.
A builder-fn keying `x2y_id` as :x2y-id, where the default gives :x-2y-id. Opt in with `:builder-fn` on the db context.
(connectable-for datasource)What code holding datasource runs a statement on: datasource when it is
an open transaction already, else the platform transaction open on this
thread on it, else datasource. A tenant request's transaction is bound to
the tenant's schema, so a store that queries through this reads the
tenant's tables.
What code holding `datasource` runs a statement on: `datasource` when it is an open transaction already, else the platform transaction open on this thread on it, else `datasource`. A tenant request's transaction is bound to the tenant's schema, so a store that queries through this reads the tenant's tables.
(context-of db)A db-context for a DataSource or Connection: it and the adapter for its engine, for code that holds a connection and must build DDL, such as a migration.
A db-context for a DataSource or Connection: it and the adapter for its engine, for code that holds a connection and must build DDL, such as a migration.
The directory migratus actually reads project-migration-dir from, as a path.
The directory migratus actually reads `project-migration-dir` from, as a path.
Create an index unless it is already there.
Create an index unless it is already there.
(current-transaction)The connection of the transaction with-transaction holds open on this
thread, or nil. For a port that takes a caller's transaction explicitly.
The connection of the transaction `with-transaction` holds open on this thread, or nil. For a port that takes a caller's transaction explicitly.
Engine, version and connection details for this context.
Engine, version and connection details for this context.
Whether x is a database context this namespace can use.
Whether `x` is a database context this namespace can use.
(delete-in-batches! ctx table where)(delete-in-batches! ctx
table
where
{:keys [id-column batch-size]
:or {id-column :id batch-size 1000}})Delete the rows of table matching where, at most batch-size per
statement, rows picked by id-column. Portable: MySQL takes no LIMIT in an
IN subquery and PostgreSQL no DELETE … LIMIT, so each batch selects its ids
first. Returns the number deleted.
Delete the rows of `table` matching `where`, at most `batch-size` per statement, rows picked by `id-column`. Portable: MySQL takes no LIMIT in an IN subquery and PostgreSQL no DELETE … LIMIT, so each batch selects its ids first. Returns the number deleted.
Every migration directory: the project's first, then each library's.
Every migration directory: the project's first, then each library's.
The libraries' migration directories that run inside every tenant schema; given the enabled libraries, only theirs.
The libraries' migration directories that run inside every tenant schema; given the enabled libraries, only theirs.
Drop a column if it is there.
Drop a column if it is there.
Drop an index if it is there.
Drop an index if it is there.
(engine-of db)Which engine a DataSource or Connection speaks: :postgresql, :mysql, :sqlite or :h2. For code holding no db-context; with one, ask its adapter (ADR-039).
Which engine a DataSource or Connection speaks: :postgresql, :mysql, :sqlite or :h2. For code holding no db-context; with one, ask its adapter (ADR-039).
(ensure-binary-collation! ctx table column column-type not-null?)On MySQL, give column of table a binary collation, keeping its
column-type ("VARCHAR(512)") and NOT NULL when not-null?. MySQL's
default collation is case-insensitive, so a key compared there merges A
and a; the other engines compare case-sensitively already. Idempotent.
On MySQL, give `column` of `table` a binary collation, keeping its
`column-type` ("VARCHAR(512)") and NOT NULL when `not-null?`. MySQL's
default collation is case-insensitive, so a key compared there merges `A`
and `a`; the other engines compare case-sensitively already. Idempotent.Run one statement over many parameter sets.
Run one statement over many parameter sets.
Run DDL, counting "already exists" as done.
Run DDL, counting "already exists" as done.
(execute-migration-ddl! ctx resource)Run the statements of the migration at classpath resource, for a module
that creates its tables at boot as well as through migrate up. On MySQL
they are rewritten as migrate up does, and an index that exists counts
as done, since the rewrite drops IF NOT EXISTS.
Run the statements of the migration at classpath `resource`, for a module that creates its tables at boot as well as through `migrate up`. On MySQL they are rewritten as `migrate up` does, and an index that exists counts as done, since the rewrite drops IF NOT EXISTS.
Run a query and return the first row, or nil.
Run a query and return the first row, or nil.
Run a query and return every row.
Run a query and return every row.
Run an insert/update/delete. Returns the update count.
Run an insert/update/delete. Returns the update count.
(in-savepoint conn f)Call f, and on failure roll back only what it did on conn: PostgreSQL
refuses every later statement of a transaction after a failed one. A nil
conn just calls f.
Call `f`, and on failure roll back only what it did on `conn`: PostgreSQL refuses every later statement of a transaction after a failed one. A nil `conn` just calls `f`.
Create the tables described by a collection of Malli schemas, if absent, and add the fields an existing one lacks.
Create the tables described by a collection of Malli schemas, if absent, and add the fields an existing one lacks.
Every table name in this database.
Every table name in this database.
An exception's message, or a summary when the driver's quotes the values sent.
An exception's message, or a summary when the driver's quotes the values sent.
(migration-connectable config)What a Clojure migration runs on: migratus's open connection, which SQLite needs used rather than a second one, or else its datasource.
What a Clojure migration runs on: migratus's open connection, which SQLite needs used rather than a second one, or else its datasource.
The name a project's own migrations are read from.
The name a project's own migrations are read from.
An identifier quoted for the engine, as stored.
An identifier quoted for the engine, as stored.
An exception fit to report or log: no SQLException in its chain quotes the values sent (BOU-630).
An exception fit to report or log: no SQLException in its chain quotes the values sent (BOU-630).
Throw when two migrations in the directories share an id, naming both.
Throw when two migrations in the directories share an id, naming both.
(f), called until it answers truthy once per k for the transaction open
on this thread; with none open, each time.
`(f)`, called until it answers truthy once per `k` for the transaction open on this thread; with none open, each time.
Project migrations no command will read because another source captures the
name — or nil. migrate up refuses while this is non-nil.
Project migrations no command will read because another source captures the name — or nil. `migrate up` refuses while this is non-nil.
Whether table exists in this database.
Whether `table` exists in this database.
(tx-connection tx)The connection behind tx when it is an open transaction: a next.jdbc
connection, or a platform transaction context. nil for anything else, a
datasource included, so a port that joins a caller's transaction can
refuse what would autocommit.
The connection behind `tx` when it is an open transaction: a next.jdbc connection, or a platform transaction context. nil for anything else, a datasource included, so a port that joins a caller's transaction can refuse what would autocommit.
(unique-conflict? e)Whether e is a write a unique key refused.
Whether `e` is a write a unique key refused.
(unpooled-connection ctx)A new connection to the database ctx is connected to, outside its pool.
Tenant migrations need one: they set search_path for the whole session,
which must not go back to the pool. The caller closes it.
A new connection to the database `ctx` is connected to, outside its pool. Tenant migrations need one: they set search_path for the whole session, which must not go back to the pool. The caller closes it.
(upsert! ctx table row key-columns)(upsert! ctx table row key-columns {:keys [update-columns]})Write row to table: update the row its key-columns match, or insert
it. Returns :updated or :inserted. :update-columns are what an update
sets, every other column by default.
No engine shares an ON CONFLICT syntax, so a writer racing to insert the same key loses with a unique conflict and tries again, finding the row. Outside a transaction a deadlock is retried too: InnoDB picks a victim among racing inserts, and inside one it has rolled back the caller's whole transaction.
Write `row` to `table`: update the row its `key-columns` match, or insert it. Returns :updated or :inserted. `:update-columns` are what an update sets, every other column by default. No engine shares an ON CONFLICT syntax, so a writer racing to insert the same key loses with a unique conflict and tries again, finding the row. Outside a transaction a deadlock is retried too: InnoDB picks a victim among racing inserts, and inside one it has rolled back the caller's whole transaction.
(with-transaction binding & body)Run body in a transaction, bound to the first name in binding.
(with-transaction [tx ctx] (execute-update! tx query1) (execute-update! tx query2))
Run `body` in a transaction, bound to the first name in `binding`. (with-transaction [tx ctx] (execute-update! tx query1) (execute-update! tx query2))
Call f with a transaction context, committing or rolling back around it.
Call `f` with a transaction context, committing or rolling back around it.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |