package plan
Import Path
github.com/freeeve/gochickpeas/gql/internal/plan (on go.dev)
Dependency Relation
imports 11 packages, and imported by 3 packages
Involved Source Files
buildSegment: lower one run of stage specs plus its projection boundary
into a Segment (port of the Rust plan.rs::build_segment, cost branch
hard-wired as the only strategy).
Anchor scan-source selection and pruning analysis for match-stage
lowering: choosing an anchor's scan source (id seek, text-index scan,
EXISTS-seed candidate scan, or the base label/property scan), deriving
the backward seed walks from a correlated EXISTS, and flagging bounded
var-expands whose duplicate endpoints can collapse under a
multiplicity-insensitive projection. Split from build.go, which holds
the segment and match-stage lowering.
CALL-procedure planning (port of the Rust plan/call.rs, grown for
expression arguments): resolve the procedure kind by name, fold constant
arguments and validate them at bind time, and map the YIELD fields to
output slots. A call with any non-constant argument is correlated: its
arguments are checked against the in-scope variables here and evaluated
per input row at exec, where a row whose arguments fail validation
yields no rows (total-eval semantics; static mistakes still error here).
Argument coercion and validation helpers for procedure resolution: each
reads one positional CALL argument (or a list form) as a typed value,
returning a plan error naming the procedure, argument, and position on a
mismatch. Split from call.go, which holds the CALL stage building and
procedure resolution.
Columnar-aggregate candidate marking: a segment whose whole job is a
bare single-label scan feeding an aggregation is a candidate for the
fused one-pass column operator (exec's tryColumnarAgg). The plan side
checks only STRUCTURE -- stage and aggregate shapes -- and never looks
at expressions or the graph; the executor classifies every filter,
group key, and aggregate argument against typed columns at run time
and falls back to the general chain when anything declines, so the
marking is purely an opportunity, never a semantic commitment. The
trigger is shape-generic by construction: any unseen query with the
same structure is marked identically.
Cardinality-aware planning helpers (port of the Rust plan/cost.rs).
Every count is an exact resident statistic, never an estimate; a probe
ABSTAINS on Param/NamedParam/Null literals (no value at plan time --
resolving one would bake a call's value into a shared cached plan), so
autoparam'd templates plan value-independently.
Heuristic forward cardinality estimates for EXPLAIN/PROFILE (port of
the Rust estimate.rs): one estimated output row-count per operator,
propagated from the anchor's exact leaf cardinality through each
expand's average fan-out, plus the reconstructed [anchor: ...] note for
each anchored MATCH stage. Estimates describe the shape of cardinality
growth, not a guarantee; they render unconditionally here (the planner
is always cost-based).
The exhaustive expression-variable walkers: the shared read descent
behind the reorder correlation guard (collectAllVars: every mentioned
name, binder locals included) and the scope-subset validators
(freeVarsOutside: free references only), plus the alpha-rename
(renameFree). A new AST kind is added here and covered by the per-kind
roll call in the walker invariant tests.
Sort-limit fusion: a trailing segment that only orders, paginates, and
re-projects the previous segment's columns forces that segment to
materialize every row it produces, even though at most skip+limit can
ever surface. Donating the ORDER BY / OFFSET / LIMIT upstream lets the
producing segment's bounded sink retain skip+limit rows and refuse the
rest before they are built (the NEXT-authored ORDER BY form of the
LDBC IC queries). The donor keeps its projection, now over the already
ordered, already truncated rows.
Early shortest-path row gating: when a segment's whole job is one
non-expanding ANY SHORTEST stage and the following boundary chain is a
pure per-row LET/FILTER pipeline, the path search plus every
gate-evaluable filter conjunct also runs INSIDE the previous segment,
inserted before its remaining expansion stages -- so rows the chain
would kill never pay the expansion (the BFS-first order a hand-written
kernel uses). The injection is a semijoin-style copy, not a move: the
downstream stages run unchanged, which keeps the transform sound by
construction -- the gate only removes rows a later deterministic
per-row filter would remove anyway (the path search is a pure function
of its endpoint pair and the graph). Bindings hide past the segment's
projected names, so nothing else can observe them.
OPTIONAL-MATCH group-join decorrelation (port of the Rust sibling's
technique): when an OPTIONAL MATCH's bindings are consumed ONLY through
bare null-skipping duplicate-decomposable aggregates grouped by outer
variables, the clause is semantically a grouped left join whose inner
pattern can be planned as a standalone query -- free to take its own
selective anchor, where the nested walk is chained to the outer rows'
bindings. The inner executes once into a key -> aggregate-values table,
each outer row binds synthetic columns by correlation-key lookup with
the aggregates' empty-group identities as the fill, and the segment
projection re-aggregates those columns (count -> sum), which reproduces
the nested left-join answer exactly, including over duplicate outer
rows.
The rewrite's dual: a SELECTIVE outer's nested walk is cheap while the
standalone inner enumerates globally, so it is gated on the estimated
outer breadth -- below the floor the nested execution stays. An
inner-side estimate gate was tried and rejected on the Rust side: the
estimator prices the inner at raw average fan, blind to the selective
anchor that actually runs.
Hash-join extraction: when a segment's bind chain re-executes an
independent branch of the pattern per row of a large intermediate (the
branch reads nothing the intermediate bound), nesting multiplies the two
branches' costs. This pass rewrites that shape into a HashJoinStage --
build the independent branch once, keyed by the variable a connecting
expand joins it back through, and probe per outer row -- purely on
estimated cardinality structure, never on query identity. It runs after
markRelUniqueness so every op keeps the uniqueness flags of the original
nested order; the executor's capture/replay protocol (see exec) makes
the reorganized row multiset exactly the nested one.
Hash-join detection: the cost model that decides where the rewrite in
hashjoin.go applies. hashJoinOnce walks the stage list once, estimating
each stage's input/output cardinality and the cumulative estimate at
which every slot was first bound, then gates pivots on the thresholds
below -- a stage worth protecting from a multiplying re-expansion. All
decisions read estimated cardinality structure, never query identity.
Package plan compiles a desugared query into the plan IR the executor
consumes: a sequence of Segments split at each projection boundary, each
a scan/expand chain plus a projection. This file holds the operator IR
(port of the Rust plan/ir.rs, minus the recognizer-only kernel specs);
planning logic lives in plan.go/build.go and the lowering helpers.
Projection-side IR: the compiled projection (ProjPlan), segments, the
whole Plan, the pre-segment stage specs, and the plan-error helper.
Core lowering primitives (port of the Rust plan/lower.rs): slot
assignment, scan-source selection, hop building, var-length
hop-predicate extraction, projection binding, and the shared AND-chain
helpers. The anchor-seek recognizers live in lower_seeks.go.
Anchor-seek recognizers (split from lower.go): the WHERE/inline-prop
conjunct forms that let a fresh node anchor on an index seek instead
of a label scan -- id equality (literal, param, and bound-variable),
substring text match, property equality, and property IN lists.
Monotonic var-length predicate pushdown (port of the Rust plan/mono.rs):
one normalizer answers "is this conjunct equivalent to sorted(L) /
reverse-sorted(L)?" over a canonicalized consecutive-pair core, and one
pass over the fully built segments lifts each recognized conjunct onto
its bounded var-expand as a MonoHopSpec so non-monotonic hops are pruned
during the walk. Mis-recognition is impossible, only missed
optimization: an unconsumed conjunct stays a correct post-hoc filter.
Plan entry points: desugar + split a query into UNION branches and
projection-boundary segments (port of the Rust plan.rs top half). The
planner is cost-based only: the Rust engine's rank/cost mode switch and
thread-local override do not exist here -- the cost branch is the one
and only strategy, layered on the same rank tiers so plan shapes match
the Rust cost mode exactly.
Projection binding (split from lower.go for the file-size norm):
compile a projection body against the segment scope, resolve ORDER BY
keys, and hoist nested aggregates into hidden accumulator slots.
Aggregating-projection helpers: substituting grouping-key subexpressions
with references to their output columns, and compiling a top-level
aggregate call into an AggCol. Split from proj_bind.go, which holds the
projection binding and nested-aggregate extraction.
Join reordering and interior-anchor splitting (split from cost.go for
the file-size norm): the cost pre-passes that run before slot
assignment, plus their name-based selectivity and correlation guards.
Clause rewrite pass (port of the Rust plan/rewrite.rs, keeping only
fuse_projection_before_aggregate -- the window-count fusion belonged to
the skipped recognizer kernels): a pure-projection boundary immediately
followed by an aggregating boundary is inlined into the aggregate, so
the preceding MATCH's scan and the aggregation land in one segment.
Shortest-path stage lowering (port of the Rust plan/sp.rs): turn an
ANY/ALL SHORTEST path-search clause into an SpStage, validating the
optional weight, extracting the per-hop predicate, and resolving the
bound endpoint slots.
MATCH-scope relationship-uniqueness marking (port of the Rust
recognize.rs::mark_rel_uniqueness): within one MATCH clause (= one
scope, spanning its comma patterns and any planner splits) every
relationship must be pairwise distinct -- ISO GQL's DIFFERENT EDGES
default match mode / openCypher's relationship isomorphism.
Small shared helpers for the planner.
Package-Level Type Names (total 33)
AggCol is one aggregate output column.
// nil for count(*)
Arg2 is the percentile aggregates' second argument, a plan-time
constant literal (a number or a parameter).
Distinct bool
Kind AggKind
OutIdx int
AggKind is an aggregate function kind.
const AggAvg
const AggCollect
const AggCount
const AggMax
const AggMin
const AggPercentileCont
const AggPercentileDisc
const AggStddevPop
const AggStddevSamp
const AggSum
BindOp is one operator of a MATCH stage's bind chain.
Acyclic forbids repeated nodes within the expansion (the ACYCLIC
path mode); the default trail semantics forbids repeated rels only.
DedupEndpoints bool
Dir graph.Direction
// expand endpoints (slots)
Kind OpKind
Target-node constraints (all ops; scan uses Slot's own).
// nil = unbounded
OpVarExpand only.
MonoHop *MonoHopSpec
Props []ast.PropEntry
// To is already bound (join/cycle/carried-in)
RelPred *RelHopPred
// slot for a named rel variable; NoSlot when unbound
// the pattern's rel variable name ("" anonymous)
// OpScan: the bound node's slot
// OpScan
// expand endpoints (slots)
Types []string
Uniq is the op's MATCH-scope relationship-uniqueness participation
(nil = untracked); OpExpand and OpVarExpand only.
BoundReturn is one projected column.
Expr ast.Expr
IsAgg bool
Name string
func OrderColIndex(expr ast.Expr, columns []string, returns []BoundReturn) int
CallProc is a CALL procedure with validated, concrete arguments.
Damping float64
Desc bool
Directed bool
Direction graph.Direction
Field string
FilterMax int64
FilterMin int64
// "" absent
Iters uint32
Kind ProcKind
Km float64
Label string
Lat float64
LatField string
Lon float64
LonField string
MaxDepth uint32
MaxLat float64
MaxLon float64
MinLat float64
MinLon float64
MinValue float64
Query string
RelType string
RelTypes []string
// "" absent
SeedVals []float64
ProcPropagate (Snapshot.PropagateBFS parameters).
Source graph.NodeID
TruncLimit int
ValueProp string
Weighted bool
func ResolveCallProc(proc string, args []value.Value) (CallProc, error)
CallStage runs a procedure, binding the yielded columns.
ArgExprs are the correlated call's argument expressions, evaluated
against each input row.
DepthSlot is algo.propagate's yielded depth slot (NoSlot if not
yielded).
NodeSlot is the yielded node column's slot (NoSlot if not yielded).
Proc is the resolved procedure. For a correlated call only its Kind
is set at plan time; the full CallProc resolves per input row from
ArgExprs.
ProcName is the procedure name of a correlated call ("" when the
arguments were constant and Proc is fully resolved).
ValueSlot is the yielded per-node scalar's slot (NoSlot if not
yielded; the search procedures have no scalar column).
*CallStage : Stage
CallSubqueryStage is CALL { subquery }: a correlated lateral join. Sub
is planned with inCols = the import list, so its first segment carries
the imported columns in slots 0..len(ImportSlots).
ImportSlots []int
OutSlots []int
Sub *Plan
*CallSubqueryStage : Stage
Estimates holds per-segment estimates in branch-major order.
Segs []SegEst
func Estimate(p *Plan, g graph.Graph) *Estimates
func github.com/freeeve/gochickpeas/gql/internal/explain.Canonical(p *Plan, est *Estimates) []string
func github.com/freeeve/gochickpeas/gql/internal/explain.Render(p *Plan, prof *explain.Profile, planTime time.Duration, est *Estimates) []string
GateDerived is one hoisted LET column: Expr evaluates against the
segment's row (path and earlier derived slots included) into Slot.
Expr ast.Expr
Slot int
Stage is one pipeline stage of a segment.
GateStage is an injected early row gate (gate.go): a copy of a later
segment's shortest-path stage plus the downstream LET/FILTER chain that
depends only on slots bound here, run before this segment's remaining
expansion stages so rows the chain would kill never expand. The path and
derived values bind to hidden slots past the segment's projected names;
the original downstream stages still run unchanged (the path search is
deterministic per endpoint pair, so re-running it is result-identical
and cheap under the pair memo).
Derived []GateDerived
Sp SpStage
Where ast.Expr
*GateStage : Stage
GroupJoinFill is a decorrelated aggregate's empty-group identity: the
value an outer row binds when the inner table has no entry for its key.
const FillNull
const FillZero
GroupJoinStage is a decorrelated OPTIONAL-MATCH aggregate join
(groupjoin.go): the OPTIONAL clause's pattern planned as a standalone
query (free to take its own selective anchor) whose projection is the
correlation keys followed by the consumed aggregates. Sub executes once
into a key -> aggregate-values table; each outer row binds OutSlots by
KeySlots lookup, with Fills as the empty-group identities. The segment
projection's aggregates are rewritten to re-aggregate the synthetic
columns (count -> sum), which reproduces the nested left-join answer
exactly, including over duplicate outer rows.
Fills []GroupJoinFill
KeySlots []int
OutSlots []int
Sub *Plan
*GroupJoinStage : Stage
HashJoinStage joins an independent branch of a MATCH scope by hash
probe instead of nested re-execution: Build's chain (which reads only
ExtSlots plus its own bindings) runs once per distinct ExtSlots value
tuple over a seed row, materializing its rows keyed by KeySlot with each
row's relationship-uniqueness pairs captured; then per outer row the
Probe expansion (the consumed connecting expand, re-oriented to run from
its outer-bound endpoint) generates key candidates whose table hits bind
PayloadSlots -- with the captured Check pairs replayed against the outer
used-pair env and the captured live pairs pushed for downstream ops, so
the row multiset is exactly the nested order's. Where carries the moved
cross-branch conjuncts evaluable once the payload binds.
Build []*MatchStage
Cartesian marks the keyless disconnected join: no expand and no
equality relates the branch, so the build materializes once and
EVERY build row emits per outer row -- the classic cartesian
build-once, which exists to stop the branch's scan re-running per
outer row (the output multiset is the same product either way).
ExtSlots []int
KeyBuild/KeyProbe carry a value-keyed join: the consumed equality
conjunct's two sides, KeyBuild reading only branch (and external)
slots, KeyProbe only pre-bound outer ones. When set, Probe and
KeySlot are unused -- the probe is a table lookup by the outer
row's key value (a null on either side never matches, per equality
semantics). This is the disconnected-components join: no expand
connects the branch, so a WHERE equality is the key.
KeyBuild/KeyProbe carry a value-keyed join: the consumed equality
conjunct's two sides, KeyBuild reading only branch (and external)
slots, KeyProbe only pre-bound outer ones. When set, Probe and
KeySlot are unused -- the probe is a table lookup by the outer
row's key value (a null on either side never matches, per equality
semantics). This is the disconnected-components join: no expand
connects the branch, so a WHERE equality is the key.
KeySlot int
PayloadSlots []int
Probe is the connecting expand: From is the outer-bound endpoint, To
is KeySlot. When Reversed, the original pattern hop ran from the
build side (its direction here is already flipped; uniqPair
canonicalization is reversal-invariant) and its target constraints
(Labels/Props) belong to the OUTER endpoint, checked once per row.
Reversed bool
Where ast.Expr
*HashJoinStage : Stage
MatchStage is one MATCH clause's bind chain. Optional rows that fail to
match survive with the stage's new variables left null (left join).
Ops []BindOp
Optional bool
PathBind is set for MATCH p = (a)-[...]->(b): assemble the named
path after the pattern binds.
Scope identifies the source MATCH clause: the relationship-
uniqueness scope spanning its comma patterns and any planner splits
(ISO GQL's DIFFERENT EDGES default / openCypher rel isomorphism).
Walk is the REPEATABLE ELEMENTS match mode: this clause's expands
take no part in relationship-uniqueness marking.
// nil when absent
*MatchStage : Stage
MonoHopSpec is a path-ordered monotonic constraint on a bounded
var-expand: each hop's RelKey property must strictly continue the order
vs the previous hop, pruned during the walk with the same three-valued
value.Compare the source filter uses (any comparable kind, not just i64).
NullsPass carries the recognized shape's null semantics: an incomparable
pair (missing key, NaN, mixed kinds) fails an all()-shape comparison and
prunes, but is not a violation in the violation-count shape and passes.
Ascending bool
NullsPass bool
RelKey string
OpKind discriminates a BindOp.
const OpExpand
const OpScan
const OpVarExpand
PathBindSpec says how to assemble a named path: the start node lives in
FromSlot, the hop's rel(s) at RelsSlot (a rel for a fixed hop, a list
for a quantified hop); the node sequence is reconstructed by walking
Dir/Types from the start, and the path value binds to PathSlot.
Dir graph.Direction
FromSlot int
PathSlot int
RelsSlot int
Types []string
Plan is a compiled query: one segment pipeline per UNION branch, the
combinators between them, and the output column names (identical across
branches, validated at plan time).
Alt is a sibling plan identical to this one except that a single
auto-parameterized anchor tie (both endpoints unbound param seeks,
whose real degrees the planner cannot see) is oriented the opposite
way. It is a FULL second planning pass, so every rewrite/recognizer
pass ran over it too -- never a spare op chain hidden inside a stage.
The cached executor resolves both anchors from the now-bound params
and runs whichever seeds from the lower-degree end; nil when the query
has no qualifying tie (the common case). Alt itself never carries an
Alt.
Branches [][]*Segment
Columns []string
Ties is how many auto-parameterized anchor ties the primary pass
collected. Alt covers the first; a count above one means the rest
stayed on the static fallback (the measurement for whether a fuller
choice mechanism would ever fire).
Union []ast.UnionKind
func Build(q *ast.Query, g graph.Graph) (*Plan, error)
func BuildWithInCols(q *ast.Query, inCols []string, g graph.Graph) (*Plan, error)
func Estimate(p *Plan, g graph.Graph) *Estimates
func github.com/freeeve/gochickpeas/gql/internal/exec.Execute(ctx *eval.Ctx, p *Plan) ([][]value.Value, error)
func github.com/freeeve/gochickpeas/gql/internal/exec.ExecuteProfiled(ctx *eval.Ctx, p *Plan) *explain.Profile
func github.com/freeeve/gochickpeas/gql/internal/explain.Canonical(p *Plan, est *Estimates) []string
func github.com/freeeve/gochickpeas/gql/internal/explain.Render(p *Plan, prof *explain.Profile, planTime time.Duration, est *Estimates) []string
PostProj is one post-aggregation scalar projection: output column Col is
computed by Expr (rewritten to read hidden __agg{k} slots) after the
groups finalize.
Col int
Expr ast.Expr
ProcKind discriminates a CallProc.
const ProcBfs
const ProcCdlp
const ProcFtsSearch
const ProcGeoWithinBBox
const ProcGeoWithinRadius
const ProcLcc
const ProcPageRank
const ProcPropagate
const ProcSssp
const ProcWcc
const ProcWccAll
ProjPlan is a compiled projection (a With boundary or the final RETURN).
Aggregated bool
Aggs []AggCol
Columns []string
Distinct bool
GroupIdx are the non-aggregate output columns (the group key).
Limit *uint64
NHidden int
OrderBy []ast.SortItem
Post are the nested-aggregate scalar wrappers; NHidden counts the
hidden accumulator slots feeding them (per-group rows are sized
len(Returns)+NHidden, truncated back after Post runs).
Returns []BoundReturn
Skip *uint64
RelHopPred is a per-hop relationship predicate lifted from
all(r IN rels(e) WHERE pred) onto a var-expand: each traversed rel must
satisfy Pred (which references only Var) or the hop is pruned.
Pred ast.Expr
Var string
RelUniq is a rel-binding op's MATCH-scope relationship-uniqueness
participation, set by markRelUniqueness only when the op's types can
intersect another rel-binding op's in the same MATCH clause (Scope) --
everything else stays untracked and zero-cost. Check means an
intersecting op binds EARLIER in execution order, so this op's
candidate rel must not reuse a pair already on the scope's used stack;
Contribute means an intersecting op binds LATER, so this op pushes its
bound rel pair(s) for those to check against. The used-rel identity is
the canonical endpoint pair (see exec's uniqPair) -- collapsing
parallel rels between one node pair, the documented multigraph
deviation, matching the trail walk's key.
Check bool
Contribute bool
Scope uint32
ScanKind discriminates a ScanSource.
const ScanAll
const ScanArg
const ScanExistsSeed
const ScanLabel
const ScanNodeID
const ScanNodeIDVar
const ScanProperty
const ScanPropertyIn
const ScanTextMatch
ScanSource is where a Scan op's candidate nodes come from.
// ScanTextMatch
// ScanProperty
Kind ScanKind
Label string
// ScanTextMatch
// ScanExistsSeed: one chain per EXISTS disjunct
// ScanArg / ScanNodeIDVar
// ScanProperty value / ScanNodeID id / ScanTextMatch needle
// ScanPropertyIn: the IN list's literals
SeedChain walks one EXISTS disjunct's pattern from its bound anchor
(AnchorSlot's row value) to the scan variable.
AnchorSlot int
Hops []SeedHop
SeedHop is one backward step of an EXISTS seed walk: traverse Types in
Dir (already reversed for the walk), landing on nodes carrying Labels.
Dir graph.Direction
Labels []string
Types []string
SegEst estimates one segment; mirrors the profiler's segment shape so
the renderer can zip them.
AnchorNotes has one entry per stage: the [anchor: ...] note for a
stage that made a cost anchor choice, else "".
PostWhereRows is the estimated rows after a boundary WHERE, if any.
ProjRows is the estimated rows after projection; nil when aggregated
(group count not estimated).
Stages []StageEst
Segment is one pipeline stage run: the stages in order, then the
projection. Output columns feed the next segment.
ColAgg marks a columnar-aggregate candidate (colagg.go): the
executor may fuse the scan, filters, and aggregation into one
typed column pass, falling back to the general chain when any
expression declines classification.
PostWhere filters projected rows (references output columns) -- the
projection boundary's WHERE.
Proj ProjPlan
RowWidth int
Slots map[string]int
Stages []Stage
func ColAggChainLen(segments []*Segment, i int) int
SpStage binds PathSlot to the minimum-hop path between the bound
endpoint slots From and To. When All, the stage is row-expanding: one
row per minimum-hop path.
All bool
Dir graph.Direction
From int
// nil = unbounded hop count
Optional bool
PathSlot int
RelPred *RelHopPred
To int
Types []string
// nil = hop-minimal
WeightVar is the path's rel variable when Weight is a per-edge
expression (bound per candidate hop).
*SpStage : Stage
*CallStage
*CallSubqueryStage
*GateStage
*GroupJoinStage
*HashJoinStage
*MatchStage
*SpStage
*UnwindStage
Package-Level Functions (total 9)
Build desugars and plans a query against g's statistics.
BuildWithInCols plans a query whose branches each begin with inCols
already bound, carried in from an outer scope (a CALL {} subquery plans
its body with inCols = its import list). Adaptive anchoring is scoped to
the top-level Build pass BY DECISION, not accident: a subquery body
executes once per outer row, so a per-execution anchor probe there
would run per row rather than per statement -- the probe's O(1)-ish
budget assumes statement frequency. Subquery bodies stay on the static
fallback until a per-row-amortized scoring exists.
ColAggChainLen is the number of segments a columnar-aggregate fusion
starting at i would consume: the scan segment itself when its own
boundary aggregates, or the scan plus a run of stage-less pure per-row
boundaries (the LET pipeline) ending in a stage-less aggregated
segment. 0 means segment i heads no fusable chain. Shared with the
executor so the plan marking and the runtime walk agree.
Estimate computes every segment's estimates for a planned query.
GroupDigits renders 2860664 as "2,860,664" (shared with the renderer).
MentionsVar reports whether e references name anywhere (binder locals
included -- over-reporting only declines an optimization, never
unsound).
OrderColIndex resolves an ORDER BY key to an output column as a whole: a
bare variable naming a projected column, or a key expression structurally
equal to a projected one. -1 when the key is a composite the executor
evaluates against the projected row instead.
ResolveCallProc validates resolved argument values into a concrete
CallProc -- at bind time for constant arguments, per input row from exec
for correlated ones.
SplitAnd walks a WHERE's top-level AND chain, appending each conjunct
(exported: the executor's conjunct bucketing splits the same chains).
Package-Level Variables (total 9)
gjAnchorDeclines counts inner plans refused as unselective with no
outer repetition to amortize the table, so tests can assert the
discriminator engaged. DisableGJAnchorDecline pins differential tests
to the always-admit behavior the discriminator replaced.
DisablePropInSeek pins result identity in tests: the label-scan +
filter evaluation must produce exactly the rows the IN seek does, in
the same order.
DisableSortLimitFusion pins result identity in tests: the unfused
pipeline must produce exactly the rows the fused one does, in the
same order.
GroupJoinMinCoverage is the minimum fraction of the correlation
variable's population the outer must reach. The standalone inner
enumerates its pattern for EVERY correlation node while the nested walk
only expands the outer's slice, so their cost ratio IS the coverage: a
broad-but-narrow outer (thousands of rows over millions of candidates)
keeps the cheap nested walk (measured: a tag-seek outer of ~4k messages
against 3M messages regressed 65x under a breadth-only gate).
GroupJoinMinOuterRows is the estimated-outer-breadth floor below which
the nested OPTIONAL execution stays (a variable so tests can force the
rewrite onto fixture-scale graphs).
HashJoinExtDivisor bounds the branch's external references: a slot
qualifies only when it was bound at a cumulative estimate at most
estIn(pivot)/HashJoinExtDivisor, which also bounds the number of
distinct memo tuples (re-builds) to the same fraction.
HashJoinFanFactor is the minimum estimated output/input multiply of
the pivot stage before the rewrite is considered.
HashJoinMaxBuildRows caps the estimated materialized branch (a
memory bound; the win condition is the pivot gate's multiply).
HashJoinMinRows is the smallest estimated intermediate worth
protecting from a multiplying re-expansion.
Package-Level Constants (total 36)
AggAvg is avg(x).
AggCollect is collect(x).
AggCount is count(x) / count(*).
AggMax is max(x).
AggMin is min(x).
AggPercentileCont / AggPercentileDisc are the two-argument
percentile aggregates: numeric values collect per group and sort at
finalize; cont interpolates linearly (always Float), disc picks the
nearest-rank collected value (Neo4j semantics). Empty group or a
percentile outside [0,1] finalizes to Null.
const AggPercentileDisc AggKind = 9 const AggStddevPop AggKind = 7
AggStddevSamp / AggStddevPop are the sample / population standard
deviations (Welford accumulation; insufficient rows finalize to 0,
matching Neo4j's stdev/stdevp).
AggSum is sum(x).
FillNull is the null-skipping aggregates' identity (sum/min/max over
an empty group is null).
FillZero is count's identity (an empty group counts zero).
NoSlot marks an absent optional slot (rel variable, group index).
OpExpand traverses one relationship hop.
OpScan binds a fresh node variable from a ScanSource.
OpVarExpand traverses a quantified (variable-length) hop. Bounded
(min>=1, max set) enumerates trails, one row per path; zero-length or
unbounded resolves the distinct reachable set via dedup'd BFS.
ProcBfs is algo.bfs(source[, directed]).
ProcCdlp is algo.cdlp([directed][, iterations][, seedProp]).
ProcFtsSearch is fts.search(label, field, searchTerm).
ProcGeoWithinBBox is geo.withinBBox(label, latField, longField, minLat, minLon, maxLat, maxLon).
ProcGeoWithinRadius is geo.withinRadius(label, latField, longField, lat, lon, km).
ProcLcc is algo.lcc([directed]).
ProcPageRank is algo.pagerank([directed][, damping][, iterations]).
ProcPropagate is algo.propagate(seeds, values, relTypes, direction,
maxDepth, valueProp, order, truncLimit[, minValue[, filterProp,
filterMin, filterMax]]) -- first-claim value propagation
(Snapshot.PropagateBFS), yielding node, value, depth per reached
node.
ProcSssp is algo.sssp(source[, directed][, weighted]).
ProcWcc is wcc(relType[, direction]).
ProcWccAll is algo.wcc().
ScanAll is every node.
ScanArg is the node already bound in row slot Slot (carried in or
reused across MATCH clauses).
ScanExistsSeed is an EXISTS-driven candidate scan: the WHERE holds
an EXISTS (or an OR of EXISTSes) correlated to the scan variable
whose pattern anchors at an already-bound variable, so candidates
enumerate backward from the anchor's current value instead of
scanning the label. Candidates are a superset (interior property
and WHERE predicates are ignored during the walk); the kept EXISTS
conjunct finalizes, so like ScanTextMatch this is purely a
narrower source.
ScanLabel is all nodes of Label.
ScanNodeID is a direct seek to the node whose id equals the Value
literal (an int or lifted param), recognized from WHERE id(n) = N.
The WHERE conjunct is kept and re-checked, so the result is identical
to the scan-then-filter.
ScanNodeIDVar is a per-row seek to the node whose id is the integer
in row slot Slot, recognized from WHERE id(n) = boundVar.
ScanProperty is an indexed anchor: nodes of Label whose Key == Value.
ScanPropertyIn is an indexed multi-value anchor: nodes of Label
whose Key equals ANY of Values, served as one property seek per
value, unioned, sorted, and deduplicated. The originating IN
conjunct is kept and re-checked, so the source only narrows.
ScanTextMatch is a substring-index candidate scan: nodes of Label
whose Field satisfies Mode (STARTS WITH/ENDS WITH/CONTAINS) against
the Value needle. Candidates are a superset; the kept WHERE conjunct
finalizes, so this is purely a faster source.
![]() |
The pages are generated with Golds v0.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. |