Skip to main content

Module expr

Module expr 

Source
Expand description

Expressions: one enum, its rendering, and the operator chain.

This is the layer bob spreads over its expr/ package. The design differs in one big way and follows bob closely in another.

The big difference. bob has a struct per shape behind a bob.Expression interface; keelson has a single Expr enum. Expressions stay inspectable — which is what Layer 4’s query rewriting needs — there is no dynamic dispatch on the hot path, Clone is cheap, and all the rendering decisions sit in one match where they can be read against the grammar. Expr::Custom holds an erased Expression so a dialect can add shapes core has never heard of.

The close following. Where the parentheses go, which separator a clause uses, when a fragment omits itself entirely — that is where bob’s real value is, and it is reproduced exactly. In particular Expr::is_atomic/Expr::grouped is bob’s expr.X, the rule that decides whether an expression is wrapped in parentheses, and it is the single most output-visible piece of logic in this module.

§Entry points

The free functions here mirror bob’s Builder methods, which means they apply the parenthesisation rule; the associated constructors on Expr build a node and nothing more. For the atomic shapes — raw, quote, literal, arg — the two are the same thing, because the rule leaves those alone.

use keelson_core::expr::{Chain, arg, quote};

let e = quote("age").gte(arg(21i32));
let (sql, args) = keelson_core::build(&Psql, &e)?;
assert_eq!(sql, r#"("age" >= $1)"#);

Structs§

CaseBuilder
A CASE expression under construction — bob’s CaseChain.
FuncExpr
A function call under construction: f("row_number", ()).over(window).

Enums§

Expr
A SQL expression, as data.
RawArg
One replacement for a ? in an Expr::Template.

Traits§

Chain
The operator chain: quote("age").gte(arg(21)).
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").

Functions§

and
(a AND b AND c).
arg
One bound argument, rendered as the dialect’s placeholder.
arg_group
Several bound arguments, parenthesised: ($1, $2, $3) — bob’s ArgGroup.
args
Several bound arguments, comma-separated and not parenthesised — for slots that bring their own parentheses, such as VALUES (..).
case
A CASE expression. See CaseBuilder.
cast
CAST(expr AS type_name).
f
A function call, optionally windowed: f("count", "*"), f("row_number", ()).over(w).
group
A parenthesised, comma-separated list. One element gives plain parentheses.
literal
A single-quoted SQL string literal — bob’s S(). literal("A") renders 'A'.
named
A named argument placeholder, for preparing a statement whose values arrive at bind time. Fails on a dialect with no named-argument syntax.
not
NOT expr.
or
(a OR b OR c).
placeholders
n unbound placeholders, comma-separated — bob’s Placeholder(n).
quote
A quoted identifier: quote("age") gives "age", quote(("users", "id")) gives "users"."id".
raw
Raw SQL, written verbatim. ? is not rewritten — see template.
template
Raw SQL with ? placeholders, rewritten into the dialect’s own syntax with args interleaved. Write \? for a literal question mark.