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— theTABLE namecommand. - update
- Mods for
psql::update. - values
- Mods for
psql::values— the standaloneVALUESstatement. - window
- Mods for a window definition — what goes inside
OVER (…)or afterWINDOW name AS.
Structs§
- Case
Builder - A
CASEexpression under construction — bob’sCaseChain. - Column
Def - One entry of a set-returning function’s column-definition list:
"a" int. - Delete
Query - A PostgreSQL
DELETE. - Distinct
SELECTDISTINCTorSELECTDISTINCT ON (a, b).- Function
- A PostgreSQL function call, with every decoration the grammar hangs off one.
- Insert
Query - A PostgreSQL
INSERT. - Merge
Insert - The
merge_insertproduction: - Merge
Query - A PostgreSQL
MERGE(PostgreSQL 15+). - Merge
When - One
WHEN … THEN …clause of aMergeQuery. - Psql
- The PostgreSQL dialect:
$1placeholders,"quoting, no named arguments. - RawQuery
- A whole statement, written by hand.
- Select
Query - A PostgreSQL
SELECT. - Table
Function - A
Functioncommitted to the from-item form: the call plusgram.y’sfunc_alias_clause,[ AS ] [ alias ] ( column_definition [, ...] ). - Table
Query - The PostgreSQL
TABLEcommand —TABLE nameisSELECT * FROM name. - Update
Query - A PostgreSQL
UPDATE. - Values
Query - A standalone PostgreSQL
VALUESstatement.
Enums§
- Error
- Everything that can go wrong while building a query.
- Expr
- A SQL expression, as data.
- Merge
Action - What a
MergeWhen’sTHENdoes. - Merge
Match Kind - Which
WHENform aMergeWhenis. - Overriding
OVERRIDING { SYSTEM | USER } VALUE, anINSERT’s treatment of an identity column.- Query
Type - Which statement a query renders.
- RawArg
- One replacement for a
?in anExpr::Template. - Value
- A bound argument.
Traits§
- Chain
- The operator chain:
quote("age").gte(arg(21)). - HasExtra
Tables - A statement whose from-item list may hold more than one entry.
- HasTarget
Table - A statement whose target table is separate from its from-item: the table an
UPDATEwrites to, or the one aDELETEremoves from. - Into
Expr - Anything that can stand where an expression is expected.
- Into
Expr List - A list of expressions: a tuple, an array, a
Vec,()for none, or a single expression standing for a one-element list. - Into
Ident - 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
CASEexpression:case_().when(cond, then).else_(other). - cast
CAST(expr AS type_name).PsqlOps::cast_tois the::shorthand.- cube
CUBE (a, b)— a grouping element covering every subset of the list.- delete
- Build a
DELETEfrom one mod. - excluded
EXCLUDED."col"— the proposed row insideON 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
INSERTfrom one mod. - merge
- Build a
MERGEfrom one mod (PostgreSQL 15+). - not
NOT expr. The operand is parenthesised if it needs it; the result is not, becauseNOTbinds looser than anything it can contain.- or
(a OR b OR c).- placeholders
nunbound placeholders, each bindingNULL, 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 — seetemplate. - 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
SELECTfrom one mod — usually a tuple of them. - subquery
- A parenthesised sub-query:
(SELECT …). - table
- Build a
TABLE namecommand from one mod — PostgreSQL’s shorthand forSELECT * FROM name. - template
- Raw SQL whose
?are rewritten to$1,$2, … withargsinterleaved. Write\?for a literal question mark. - update
- Build an
UPDATEfrom one mod. - values
- Build a standalone
VALUESstatement from one mod.
Type Aliases§
- Result
- The result type used throughout keelson.