Rindle docs and package mapSkip to main content

Module family_key

Module family_key 

Source
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 direct Simple children of a top-level And — whose op is =, whose LHS is a column, and whose literal is a scalar a family may bind on ([canon_of_lit]: not Null, 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 right replaced in position by {"hole": i}. Position is kept deliberately: conjunct order participates in the template (design §3.1 — there is no normalize_ast pass), so And[a=?, b>3] and And[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 (an And left 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 yields Ok(None) and falls back to today’s per-query materialization, byte for byte. Everything outside the holes — related structure, subquery literals, order_by, limit, one, select, start — stays in the key, so it separates families exactly as it separates QueryKeys.

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 (xx_0); the stripped template’s singleton does not, and the builder refuses the collision. Such a query stays a singleton.

Structs§

FamilyExtraction
The result of a successful extraction: the family the query belongs to, the template its pipeline compiles from, and the binding this query is.
FamilyKey
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.
FamilyTemplate
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 (what instantiate needs 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 its QueryKey — today’s path, byte for byte. Err only on the (practically unreachable) serialization failure QueryKey shares.

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 are Arc<str>), so it crosses worker command channels.