Skip to main content

Crate keelson_mysql

Crate keelson_mysql 

Source
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.

absentwhy
RETURNINGMySQL has none, on any statement. There is no Returning field in this crate.
FETCH … ROWS ONLYnot in the grammar; LIMIT is the only row limiter.
DISTINCT ONPostgreSQL’s. select::distinct is the whole of MySQL’s.
FULL JOINnot in the grammar. Three join kinds plus CROSS and STRAIGHT_JOIN.
NULLS FIRST / NULLS LAST, USING operatornot in ORDER BY; the chain has asc, desc and collate.
GROUPS frame mode, EXCLUDEnot in the frame clause.
FILTER (WHERE …), WITHIN GROUPnot on a function call.
ROLLUP(…), CUBE(…), GROUPING SETS(…), GROUP BY DISTINCTGROUP BY … WITH ROLLUP is the only super-aggregate.
ON CONFLICTMySQL’s upsert is ON DUPLICATE KEY UPDATE, and REPLACE.
WITH on INSERT/REPLACEpermitted only immediately before the sub-SELECT.
TABLESAMPLE, ONLY, WITH ORDINALITYPostgreSQL’s from-item decorations.
IS DISTINCT FROMon 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 — the TABLE statement (MySQL 8.0.19+).
update
Mods for mysql::update.
values
Mods for mysql::values — the VALUES statement (MySQL 8.0.19+).
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.
DeleteQuery
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).
InsertQuery
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.
ReplaceQuery
A MySQL REPLACE.
RowAlias
AS row_alias [(col_alias, …)], the name an INSERT’s new row is given (MySQL 8.0.19).
SelectQuery
A MySQL SELECT.
TableQuery
The MySQL TABLE statement (MySQL 8.0.19+) — TABLE t is SELECT * FROM t.
UpdateQuery
A MySQL UPDATE.
ValuesQuery
The MySQL VALUES statement (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.
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)).
HasDeleteTables
A DELETE’s FROM list — the tables rows are actually removed from.
HasDuplicateKeyUpdate
A statement with an ON DUPLICATE KEY UPDATE assignment list.
HasExtraTables
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.
HasRowAlias
A statement that names its incoming row — only INSERT does.
HasTargetTable
A statement whose table list is the thing being modified: the table_references an UPDATE writes to.
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.
MysqlOps
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 CASE expression: case_().when(cond, then).else_(other).
cast
CAST(expr AS type_name).
delete
Build a DELETE from 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 INSERT from 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, 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.
replace
Build a REPLACE from one mod.
row_value
`alias`.`col` — the incoming row’s column, through the row alias set by insert::as_.
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 statement from one mod (MySQL 8.0.19+) — MySQL’s shorthand for SELECT * FROM t.
template
Raw SQL whose ? are rewritten 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 (MySQL 8.0.19+).
values_of
VALUES(col) — the value the INSERT proposed for col.

Type Aliases§

Result
The result type used throughout keelson.