Expand description
The MySQL dialect for keelson.
Five statement types, each shaped by the production in the MySQL 8.4 reference manual, plus the mods that fill them in and the expression starters they are filled in with.
use keelson_mysql as mysql;
use keelson_mysql::{Chain, Query, arg, quote, select};
let q = mysql::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, "SELECT `id`, `name` FROM `users` WHERE (`age` >= ?)");
assert_eq!(args, vec![keelson_core::Value::I32(21)]);§Where this sits
Layer 1 of keelson, for MySQL. 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). MySQL’s missing RETURNING is visible up
there: a generated MySQL model reads a row back by key instead. The whole
map is the keelson facade crate.
§How it is put together
A starter is a function of one mod. mysql::select(mods) takes a single
impl Mod<SelectQuery> — and a tuple of mods is a mod, so mysql::select(())
and mysql::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. mysql::select is a function
and a module: Rust keeps values and modules in separate namespaces, so
mysql::select((select::from("users"),)) needs no import gymnastics. The modules
are named after the statement — select, insert, replace, update,
delete, window, frame — never bob’s sm/im/um/dm/wm/fm.
A mod is written once. The mods live in shared, generic over the
keelson_core::clause Has* trait they need, and each statement module
re-exports the ones that apply to it. 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` .
§What MySQL does not have
The list is worth reading before looking for a mod that is not here, because each absence is deliberate — a construct a dialect lacks does not exist for it.
| absent | why |
|---|---|
RETURNING | MySQL has none, on any statement. There is no Returning field in this crate. |
FETCH … ROWS ONLY | not in the grammar; LIMIT is the only row limiter. |
DISTINCT ON | PostgreSQL’s. select::distinct is the whole of MySQL’s. |
FULL JOIN | not in the grammar. Three join kinds plus CROSS and STRAIGHT_JOIN. |
NULLS FIRST / NULLS LAST, USING operator | not in ORDER BY; the chain has asc, desc and collate. |
GROUPS frame mode, EXCLUDE | not in the frame clause. |
FILTER (WHERE …), WITHIN GROUP | not on a function call. |
ROLLUP(…), CUBE(…), GROUPING SETS(…), GROUP BY DISTINCT | GROUP BY … WITH ROLLUP is the only super-aggregate. |
ON CONFLICT | MySQL’s upsert is ON DUPLICATE KEY UPDATE, and REPLACE. |
WITH on INSERT/REPLACE | permitted only immediately before the sub-SELECT. |
TABLESAMPLE, ONLY, WITH ORDINALITY | PostgreSQL’s from-item decorations. |
IS DISTINCT FROM | on the shared chain and not valid MySQL; use MysqlOps::null_safe_eq. |
§Sub-queries
The statement 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 derived table, a scalar
sub-expression — use subquery. Placeholders re-index across the nesting on
their own, because the counter belongs to the writer; that matters here even
though every MySQL placeholder looks the same, because the argument order is
what the counter fixes.
Modules§
- delete
- Mods for
mysql::delete. - frame
- Mods for a window frame — which rows around the current one a window function sees.
- insert
- Mods for
mysql::insert. - replace
- Mods for
mysql::replace. - select
- Mods for
mysql::select. - shared
- The mods, written once against the
Has*traits and re-exported per statement. - table
- Mods for
mysql::table— theTABLEstatement (MySQL 8.0.19+). - update
- Mods for
mysql::update. - values
- Mods for
mysql::values— theVALUESstatement (MySQL 8.0.19+). - window
- Mods for a window definition — what goes inside
OVER (…)or afterWINDOW name AS.
Structs§
- Case
Builder - A
CASEexpression under construction — bob’sCaseChain. - Delete
Query - A MySQL
DELETE. - Function
- A MySQL function call, with every decoration the grammar hangs off one.
- Hints
- The
/*+ … */optimizer-hint comment that may follow a statement’s first keyword (10.9.2 Optimizer Hints). - Insert
Query - A MySQL
INSERT. - Modifiers
- The modifiers of one statement, kept in grammar order.
- Mysql
- The MySQL dialect:
?placeholders, backtick quoting, no named arguments. - RawQuery
- A whole statement, written by hand.
- Replace
Query - A MySQL
REPLACE. - RowAlias
AS row_alias [(col_alias, …)], the name anINSERT’s new row is given (MySQL 8.0.19).- Select
Query - A MySQL
SELECT. - Table
Query - The MySQL
TABLEstatement (MySQL 8.0.19+) —TABLE tisSELECT * FROM t. - Update
Query - A MySQL
UPDATE. - Values
Query - The MySQL
VALUESstatement (MySQL 8.0.19+).
Enums§
- Error
- Everything that can go wrong while building a query.
- Expr
- A SQL expression, as data.
- Modifier
- One of MySQL’s statement modifiers — the keywords between a statement’s first word and its real content.
- 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)). - HasDelete
Tables - A
DELETE’sFROMlist — the tables rows are actually removed from. - HasDuplicate
KeyUpdate - A statement with an
ON DUPLICATE KEY UPDATEassignment list. - HasExtra
Tables - A statement whose table list may hold more than one entry.
- HasHints
- A statement that takes optimizer hints — all four of them do.
- HasModifiers
- A statement that takes MySQL’s modifier keywords.
- HasRow
Alias - A statement that names its incoming row — only
INSERTdoes. - HasTarget
Table - A statement whose table list is the thing being modified: the
table_referencesanUPDATEwrites to. - 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.
- Mysql
Ops - The operators MySQL 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
?. - arg_
group - Several bound arguments, parenthesised:
(?, ?, ?). - 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).- delete
- Build a
DELETEfrom one mod. - f
- A function call:
f("COUNT", "*"),f("ROW_NUMBER", ()).over(()). - group
- A parenthesised, comma-separated list:
(a, b). One element gives plain parentheses. - insert
- Build an
INSERTfrom one mod. - match_
against MATCH (cols) AGAINST (search)in natural-language mode.- match_
against_ mode MATCH (cols) AGAINST (search IN BOOLEAN MODE), or any other search modifier written out.- 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.
- replace
- Build a
REPLACEfrom one mod. - row_
value `alias`.`col`— the incoming row’s column, through the row alias set byinsert::as_.- 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
TABLEstatement from one mod (MySQL 8.0.19+) — MySQL’s shorthand forSELECT * FROM t. - template
- Raw SQL whose
?are rewritten withargsinterleaved. Write\?for a literal question mark. - update
- Build an
UPDATEfrom one mod. - values
- Build a standalone
VALUESstatement from one mod (MySQL 8.0.19+). - values_
of VALUES(col)— the value theINSERTproposed forcol.
Type Aliases§
- Result
- The result type used throughout keelson.