Expand description
FamilyKey — the identity of a parameterized query family (design 310 §3):
the QueryKey construction over a query’s template,
the canonical AST with its eligible root-equality literals punched into holes. Two
subscriptions are family-mates iff their FamilyKeys are equal; the extracted
literal tuple — the Binding, a [CanonKey] — is what distinguishes them.
Extraction is pure data work: no schema, no builder, no engine. What it decides:
- Which literals are holes (design §3.1): the RHS of every root-level equality
conjunct — the single top-level
Simple, or the directSimplechildren of a top-levelAnd— whose op is=, whose LHS is a column, and whose literal is a scalar a family may bind on ([canon_of_lit]: notNull, not an array). Every eligible conjunct is holed, no inference: two ASTs group iff they agree everywhere else, and a conjunct whose literal happens to agree across bindings simply contributes a constant column to the binding tuple. - What the key hashes (impl plan D2): the canonical JSON of the
number-canonicalized AST with each holed conjunct’s
rightreplaced in position by{"hole": i}. Position is kept deliberately: conjunct order participates in the template (design §3.1 — there is nonormalize_astpass), soAnd[a=?, b>3]andAnd[b>3, a=?]are different families. A key over the stripped AST alone would silently widen grouping. - What the builder compiles (
FamilyTemplate::stripped): the same canonical AST with the holed conjuncts removed (anAndleft with one child collapses to that child; zero ⇒where: None), so the engine’s family root connection carries only the residual predicate and the membership test replaces the holes. - What does not group (design §3.2): an aggregate root (
aggregate/group_by/having) is refused outright; a query with no eligible conjunct yieldsOk(None)and falls back to today’s per-query materialization, byte for byte. Everything outside the holes —relatedstructure, subquery literals,order_by,limit,one,select,start— stays in the key, so it separates families exactly as it separatesQueryKeys.
One shape the engine’s alias normalization would otherwise reject is also refused
here: when stripping leaves the root where a bare EXISTS whose alias collides
with a materialized related of the same name. The concrete query’s And gets that
alias uniquified (x → x_0); the stripped template’s singleton does not, and the
builder refuses the collision. Such a query stays a singleton.
Structs§
- Family
Extraction - The result of a successful extraction: the family the query belongs to, the template its pipeline compiles from, and the binding this query is.
- Family
Key - Every daemon-side input that can affect the emitted rows of a family: the same four
fields as
QueryKey, with the canonical template bytes in place of the canonical AST bytes. - Family
Template - The compiled half of a family: the stripped AST the builder lowers, plus the names
of the holed columns (the partition key, resolved to
ColIds by the builder) and each hole’s position among the original top-level conjuncts (whatinstantiateneeds to be an exact inverse).
Functions§
- extract_
family - Extract
ast’s family, if it can join one (module docs).Ok(None)⇒ the query cannot join any family and falls back to itsQueryKey— today’s path, byte for byte.Erronly on the (practically unreachable) serialization failureQueryKeyshares.
Type Aliases§
- Binding
- A family member’s parameter tuple: the canonical literal of each holed conjunct, in
hole order. A [
CanonKey] (impl plan D1) — the same type the engine’s partition membership test and the daemon’s per-partition demux key by, so the three agree by construction.Send + Sync(the payloads areArc<str>), so it crosses worker command channels.