Skip to main content

Crate keelson_psql

Crate keelson_psql 

Source
Expand description

The PostgreSQL dialect for keelson.

The statement types — SELECT, INSERT, UPDATE, DELETE, MERGE, and the VALUES and TABLE shorthands — each shaped by the production in PostgreSQL’s own reference manual, plus the mods that fill them in and the expression starters they are filled in with.

use keelson_psql as psql;
use keelson_psql::{Chain, Query, arg, quote, select};

let q = psql::select((
    select::columns((quote("id"), quote("name"))),
    select::from(quote("users")),
    select::where_(quote("age").gte(arg(21i32))),
));

let (sql, args) = q.build()?;
assert_eq!(sql, r#"SELECT "id", "name" FROM "users" WHERE ("age" >= $1)"#);
assert_eq!(args, vec![keelson_core::Value::I32(21)]);

§Where this sits

Layer 1 of keelson, for PostgreSQL. It is a complete way to use keelson on its own: it depends only on keelson-core and produces a SQL string and an argument list, which you may run with any driver you like. To run it through keelson, add Layer 2 (keelson-exec plus a backend such as keelson-sqlx); to have typed models built out of these mods, add Layers 3 and 4 (keelson-models, keelson-gen). The whole map, and one dependency line for it, is the keelson facade crate.

§How it is put together

A starter is a function of one mod. psql::select(mods) takes a single impl Mod<SelectQuery> — and a tuple of mods is a mod, so psql::select(()) and psql::select((a, b, c)) are both that one argument. Arity is never a ceiling, because tuples nest.

A mod module shares its name with its starter. psql::select is a function and a module: Rust keeps values and modules in separate namespaces, so psql::select((select::from("users"),)) needs no import gymnastics. The modules are named after the statement — select, insert, update, delete, window, frame — never bob’s sm/im/um/dm/wm/fm.

A mod is written once. The mods live in one place, generic over the keelson_core::clause Has* trait they need, and each statement module re-exports the ones that apply to it. select::where_ and update::where_ are the same function; insert::where_ is too, and resolves only against the ON CONFLICT … DO UPDATE body, because an INSERT has no WHERE of its own. An inapplicable mod is a compile error.

A raw &str works wherever an expression does. Every slot takes impl IntoExpr, and a &'static str is raw SQL. select::from("users") writes FROM users; select::from(quote("users")) writes FROM "users".

§Sub-queries

The four query types implement IntoExpr, so one goes straight into any expression slot: select::union(other), select::with("c", other), insert::query(other). Those slots supply their own parentheses. Where the parentheses belong to the sub-query itself — a FROM item, a scalar sub-expression — use subquery. Placeholders re-index across the nesting on their own, because the counter belongs to the writer.

Modules§

delete
Mods for psql::delete.
frame
Mods for a window frame — which rows around the current one a window function sees.
insert
Mods for psql::insert.
merge
Mods for psql::merge (PostgreSQL 15+).
select
Mods for psql::select.
shared
The mods, written once against the Has* traits and re-exported per statement.
table
Mods for psql::table — the TABLE name command.
update
Mods for psql::update.
values
Mods for psql::values — the standalone VALUES statement.
window
Mods for a window definition — what goes inside OVER (…) or after WINDOW name AS.

Structs§

CaseBuilder
A CASE expression under construction — bob’s CaseChain.
ColumnDef
One entry of a set-returning function’s column-definition list: "a" int.
DeleteQuery
A PostgreSQL DELETE.
Distinct
SELECT DISTINCT or SELECT DISTINCT ON (a, b).
Function
A PostgreSQL function call, with every decoration the grammar hangs off one.
InsertQuery
A PostgreSQL INSERT.
MergeInsert
The merge_insert production:
MergeQuery
A PostgreSQL MERGE (PostgreSQL 15+).
MergeWhen
One WHEN … THEN … clause of a MergeQuery.
Psql
The PostgreSQL dialect: $1 placeholders, " quoting, no named arguments.
RawQuery
A whole statement, written by hand.
SelectQuery
A PostgreSQL SELECT.
TableFunction
A Function committed to the from-item form: the call plus gram.y’s func_alias_clause, [ AS ] [ alias ] ( column_definition [, ...] ).
TableQuery
The PostgreSQL TABLE command — TABLE name is SELECT * FROM name.
UpdateQuery
A PostgreSQL UPDATE.
ValuesQuery
A standalone PostgreSQL VALUES statement.

Enums§

Error
Everything that can go wrong while building a query.
Expr
A SQL expression, as data.
MergeAction
What a MergeWhen’s THEN does.
MergeMatchKind
Which WHEN form a MergeWhen is.
Overriding
OVERRIDING { SYSTEM | USER } VALUE, an INSERT’s treatment of an identity column.
QueryType
Which statement a query renders.
RawArg
One replacement for a ? in an Expr::Template.
Value
A bound argument.

Traits§

Chain
The operator chain: quote("age").gte(arg(21)).
HasExtraTables
A statement whose from-item list may hold more than one entry.
HasTargetTable
A statement whose target table is separate from its from-item: the table an UPDATE writes to, or the one a DELETE removes from.
IntoExpr
Anything that can stand where an expression is expected.
IntoExprList
A list of expressions: a tuple, an array, a Vec, () for none, or a single expression standing for a one-element list.
IntoIdent
The parts of a qualified identifier: "age", or ("users", "id").
Mod
Something that modifies a query in place.
PsqlOps
The operators PostgreSQL has and the other two dialects do not.
Query
A complete, runnable statement.

Functions§

and
(a AND b AND c).
arg
One bound argument, rendered $n.
arg_group
Several bound arguments, parenthesised: ($1, $2, $3).
args
Several bound arguments, comma-separated and not parenthesised — for a slot that brings its own, such as VALUES (…).
case_
A CASE expression: case_().when(cond, then).else_(other).
cast
CAST(expr AS type_name). PsqlOps::cast_to is the :: shorthand.
cube
CUBE (a, b) — a grouping element covering every subset of the list.
delete
Build a DELETE from one mod.
excluded
EXCLUDED."col" — the proposed row inside ON CONFLICT DO UPDATE.
f
A function call: f("count", "*"), f("row_number", ()).over(()).
group
A parenthesised, comma-separated list: (a, b). One element gives plain parentheses.
grouping_sets
GROUPING SETS ((a), (b), ()) — the sets listed explicitly.
insert
Build an INSERT from one mod.
merge
Build a MERGE from one mod (PostgreSQL 15+).
not
NOT expr. The operand is parenthesised if it needs it; the result is not, because NOT binds looser than anything it can contain.
or
(a OR b OR c).
placeholders
n unbound placeholders, each binding NULL, so a statement can be prepared now and its values supplied by whatever rebinds it.
query
A query as an expression, not parenthesised.
quote
A quoted identifier: quote("age") gives "age", quote(("users", "id")) gives "users"."id".
raw
Raw SQL, verbatim. ? is left alone — see template.
raw_query
A whole statement, written by hand, as a runnable query.
rollup
ROLLUP (a, b) — a grouping element covering every prefix of the list.
s
A single-quoted string literal — bob’s S. s("A") renders 'A'.
select
Build a SELECT from one mod — usually a tuple of them.
subquery
A parenthesised sub-query: (SELECT …).
table
Build a TABLE name command from one mod — PostgreSQL’s shorthand for SELECT * FROM name.
template
Raw SQL whose ? are rewritten to $1, $2, … with args interleaved. Write \? for a literal question mark.
update
Build an UPDATE from one mod.
values
Build a standalone VALUES statement from one mod.

Type Aliases§

Result
The result type used throughout keelson.