SQLR-6 — one GROUP BY key: an optionally-qualified column reference
(dept or t.dept). The qualifier matters for joined SELECTs,
where the same column name can exist on several in-scope tables;
the single-table path validates it against the FROM table/alias
(SQLR-14), mirroring projection qualifiers.
One JOIN clause from the FROM list. Multi-join queries
(A JOIN B ... JOIN C ...) become a Vec<JoinClause> evaluated
left-to-right against the accumulator. The match condition is one
of ON / USING / NATURAL (see JoinConstraintKind);
CROSS JOIN arrives here already rewritten to ON true.
A parsed ORDER BY clause: a single sort key (expression), ascending
by default. Phase 7b widened this from “bare column name” to
“arbitrary expression” so KNN queries of the form
ORDER BY vec_distance_l2(col, [...]) LIMIT k work end-to-end. The
expression is evaluated per-row at execution time via eval_expr;
the simple ORDER BY col form still works because that’s just an
Expr::Identifier taking the same path.
What the aggregate is fed: * (only valid for COUNT) or a column
reference. SQLR-6 — the column carries its optional t. qualifier
so joined aggregation (SUM(orders.amount)) can disambiguate
same-named columns across in-scope tables; the single-table path
validates it against the FROM table/alias (SQLR-14), same as
projection qualifiers.
How a JOIN matches rows. SQLR-5 originally shipped ON only; the
USING / NATURAL increment adds the two name-based constraints.
ON carries its predicate straight from the parser. USING and
NATURAL defer their equality synthesis to the executor because
they need table schemas (which column names exist, and — for
NATURAL — which are shared) that the parser doesn’t have. The
executor turns both into the same left.col = right.col [AND …]
predicate the ON path already evaluates. CROSS JOIN is rewritten
to ON true at parse time (no schema needed) and so reuses the
On variant directly.
SQLR-5 — flavor of join. SQLite ships INNER and LEFT OUTER; we
implement the full quartet on top of a single nested-loop driver
because the per-flavor differences are small (NULL-padding policy
for unmatched left/right rows). RIGHT OUTER and FULL OUTER aren’t
in SQLite — see docs/design-decisions.md for the rationale.