Involved Source Files Per-candidate predicate specialization: during one bind-chain level's
candidate iteration every row slot except the level's own is fixed, so
a pushed-down conjunct is a unary function of the candidate id. The
dominant conjunct shape -- the fused prop-vs-const comparison -- runs
as a monomorphic closure reading its hoisted typed column directly,
skipping the compiled tree's dispatch and per-candidate boxing. Every
pairing whose comparison semantics are not trivially same-kind boxes
the column value once and routes through value.Compare, so results are
exactly the general path's (missing property = failed compare = Null =
prune, for all six operators). Per-row evaluation of a compiled expression, mirroring the interpreter
exactly (the shared eval kernels keep the arithmetic, comparison, and
function semantics identical). Expr -> CExpr lowering: hot leaves (slots, property reads) carry
resolved indices/readers; correlated subqueries gain a result memo keyed
on their outer reads; scalar functions with constant arguments fold at
compile time; the remaining rarely-hot nodes fall back to the
interpreter. Correlated-subquery decorrelation setup: recognizing a cheap bound-pair
EXISTS probe, computing a subquery's outer-slot memo key, and marking a
COUNT{} decorrelatable when it is a fixed linear chain between two
outer-bound endpoints with no other outer dependency (evaluated once per
anchor instead of a DFS per row). Split from compile.go, which holds the
compiled-node types and the expression compiler. Canonical identity for a decorrelated COUNT{} side table: a byte string
over the subquery's pattern and WHERE with the anchor and group
variables substituted by positional markers, so two sibling subqueries
differing only in what the outer query names those endpoints (BI Q8's
C1(person)/C1(friend)) canonicalize identically and share one table per
anchor node. Fail-closed: any construct the encoder does not cover
yields no identity and the node keeps a private table -- sharing is an
optimization, never a semantic commitment. Parameters encode by slot or
name, which is sound because tables are shared only within one
execution's Ctx, where parameter values are fixed. IN-list hoisting and slot analysis: a batch-constant list bakes to a
prebuilt membership index (cInConst); a loop-invariant carried list
rebuilds once per match-call (cInCarried); Slots reports the row slots a
compiled expression reads for WHERE pushdown. Package compile lowers a bound expression into a CExpr whose leaves
carry resolved row slots and typed Snapshot column readers, so per-row
evaluation does no string hashing (the var->slot and key->column lookups
happen once at stage compile). Evaluation mirrors the interpreter
exactly; nodes not worth specializing fall back to it. Port of the Rust
compile.rs -- the one package besides the graph seam that touches the
engine directly. Whole-row predicate specialization: a comparison whose sides are
property reads over typed i64 columns (optionally shifted by a constant
integer or months-free duration) -- the dominant fully-bound filter
shape, e.g. a temporal ordering between two pattern variables -- runs as
a monomorphic closure reading both columns directly, skipping the
compiled tree's dispatch and per-row boxing. A slot-vs-slot comparison
flattens to one shared-kernel Compare call. Rows whose slots do not
hold nodes fall back to the full tree evaluation, so results are exactly
the general path's for every input.
Package-Level Type Names (total 4)
/* sort by: | */
CandBatch sweeps a whole candidate buffer for one conjunct: it clears
keep[i] for every candidate that fails, touching only still-kept
entries. The batch form exists for shapes whose per-candidate work is
pure array arithmetic -- no closure call, no dispatch per element.
func CandidateBatch(c *Compiled, slot int) (CandBatch, bool)
CandPred reports whether the conjunct holds for a node candidate bound
at its specialized slot. The row carries the level's fixed outer
bindings -- only the carried-list rebuild (once per match-call epoch)
reads it; hot paths touch the candidate alone.
func CandidatePred(c *Compiled, slot int, slots map[string]int) (CandPred, bool)
IntSweep bulk-filters a candidate chunk over an i64 NODE column
against a folded constant: one GetMany then a hoisted compare loop --
the batch form of the cCmpPropConst per-candidate predicate for
columns the windowed CandidateBatch cannot serve (narrow storage
classes) and constants it declines (temporals, which fold to their
epoch millis and compare through the exact int order, per constI64Val).
vals/present are caller scratch of at least len(ids); keep is the
running mask. Candidates must be node ids, the same contract as
CandidateBatch.
func CandidateIntSweep(c *Compiled, slot int) (IntSweep, bool)
Package-Level Functions (total 8)
CandidateBatch specializes c to a buffer sweep when its shape allows
the columnar form: today the fused prop-vs-const comparison over an
i64 column with a contiguous-presence window (SliceRange), where the
filter reduces to vals[id-start] compared against a pre-encoded
constant -- the dominant pushed-down filter shape over LDBC-style
label-block columns. Semantics mirror the scalar predicate exactly
(value.Compare's float64 partial order; out-of-window = absent =
prune). ok=false keeps the scalar path.
CandidateIntSweep specializes a compiled conjunct to an IntSweep;
ok=false leaves the caller on the per-candidate path.
CandidatePred specializes c when its only per-candidate dependency is
the node at slot and its shape is the fused prop-vs-const comparison or
a constant- or carried-list membership over the candidate's property
(or over the candidate itself: a bare-variable element probes the node
value directly, no read at all); ok=false keeps the general row
evaluation.
ConstValue reports the expression's compile-time constant value: the
bottom-up literal folding is the one authority on constness (a slot or
property read never folds), so ok=false exactly when evaluation could
depend on a row. slots must be the caller's real slot map -- with an
empty map an unbound name folds to a null LITERAL, which would launder
row-dependent expressions (coalesce(m.ts, d) folds to d) into
constants.
HoistCarriedIn rewrites remaining IN nodes whose list reads only
carried-in slots (loop-invariant per match-call, not batch-constant)
into the per-epoch cached form. Applied after HoistConstIn so
batch-constant lists keep their cheaper baked set.
HoistConstIn rewrites IN nodes whose list is invariant over the row
batch (every slot it reads is batch-constant, no slow node) into a baked
membership index, evaluated once against a sample row.
New compiles e against the segment's slots and snapshot. Parameters
resolve at compile time (their values are constant for the execution).
Slots collects the row slots a compiled expression reads; hasSlow is set
for nodes whose inner references aren't slot-resolved (interpreter
fallbacks, functions, subqueries without a memo set). A memoized
subquery reads exactly its memo slots, so it can push down to where its
correlated bindings bind -- but hasWalk reports it separately, because
the memo only bounds REPEAT cost: on every distinct correlation tuple
the subquery still walks the graph, so its placement must respect walk
cost, not just read placement (task 115: classify by what the predicate
DOES, not by which evaluation path it takes).
Package-Level Variables (only one)
SubqueryWalks counts actual correlated-subquery graph walks (memo
misses and unmemoized evaluations) -- the load-independent oracle for
predicate-placement tests: a walk that runs before a shrinking op is
visible as walk count, never as a row difference.
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.