// 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.
package planimport ()// anchorCard is the measured leaf cardinality of anchoring on n (lower =// fewer rows to start from). Mirrors the rank tiers so cardinality never// inverts a rank decision -- it only refines a same-tier tie: bound -> 0,// id seek -> 1, concrete property seek -> exact posting length, labelled// -> label cardinality, else node count.func anchorCard( *ast.NodePat, ast.Expr, map[string]int, map[int]bool, graph.Graph) uint64 {if .Var != "" {if , := [.Var]; && [] {return0 }ifidSeekLiteral(, .Var) != nil || idSeekVar(, .Var, , ) != NoSlot {return1 } }iflen(.Labels) > 0 { := .Labels[0] := int64(-1)// The costed seek is the SAME one scanSource builds (bestPropSeek is the // shared oracle over inline props and WHERE equalities), so the rank that // justifies this anchor can never be a posting list the lowerer discards. // A param seek abstains -- no plan-time value -- and falls through to the // label-wide cardinality below.if , := bestPropSeek(, , ); && !.abstain { = int64(.card) }if .Var != "" {if := textMatchSeek(, .Var); != nil && .needle.Kind == ast.LitStr {if , := .SubstringCandidates(, .field, .needle.S); { := int64(setLen())if < 0 || < { = } } } }if >= 0 {returnuint64() }return .LabelCardinality() }returnuint64(.NodeCount())}// resolveAnchorNodes pins a node pattern to the concrete node id(s) it// anchors on at plan time; ok=false when it can't be pinned (bound, a// param seek with no plan-time value, or label-only).func resolveAnchorNodes( *ast.NodePat, ast.Expr, map[string]int, map[int]bool, graph.Graph) ([]graph.NodeID, bool) {if .Var != "" {if , := [.Var]; && [] {returnnil, false }if := idSeekLiteral(, .Var); != nil && .Kind == ast.LitInt {return []graph.NodeID{graph.NodeID(.I)}, true } }iflen(.Labels) == 0 {returnnil, false }// Resolve the SAME prop scanSource seeks (bestPropSeek), so the exact-degree // read here matches the plan actually built. A param seek abstains (no // plan-time value).if , := bestPropSeek(, , ); && !.abstain {if .inVals != nil {var []graph.NodeIDfor , := range .inVals { = append(, seekNodes(, .Labels[0], .key, semantics.LitValue())...) }slices.Sort()returnslices.Compact(), true }returnseekNodes(, .Labels[0], .key, semantics.LitValue(.val)), true }returnnil, false}// resolvedFirstHopDegree is the exact fan-out of the FIRST hop when a// pattern is anchored on its resolved start: the real degree of the// resolved node(s) over the first hop's types and direction. One hop only,// an exact resident count, never a multi-hop product. ok=false when the// start can't be resolved or there is no hop.func resolvedFirstHopDegree( *ast.Pattern, ast.Expr, map[string]int, map[int]bool, graph.Graph) (uint64, bool) {iflen(.Hops) == 0 {return0, false } , := resolveAnchorNodes(&.Start, , , , )if ! {return0, false } := &.Hops[0].Rel := mapDir(.Dir)varuint64for , := range { += countNeighbors(, , , .Types) }return , true}// bothEndsUnboundParamSeek reports whether both of a hop pattern's endpoints// are labelled, unbound, and seeked only by a parameter-valued property --// the shape whose real anchor degree is unknown at plan time (the param has// no value yet) but known at execution. A concrete property on an endpoint// would let the degree probe resolve it, so it is NOT this case; a label-only// endpoint is a genuine unknown with no value arriving later, so also not.func bothEndsUnboundParamSeek( *ast.Pattern, map[string]int, map[int]bool) bool {returnisUnboundParamSeek(&.Start, , ) && isUnboundParamSeek(.EndNode(), , )}// isUnboundParamSeek reports whether n is a labelled, not-yet-bound node whose// only concrete seek is a parameter-valued property (no literal property that// would resolve at plan time).func isUnboundParamSeek( *ast.NodePat, map[string]int, map[int]bool) bool {if .Var != "" {if , := [.Var]; && [] {returnfalse } }iflen(.Labels) == 0 {returnfalse } := falsefor := range .Props {switch .Props[].Val.Kind {caseast.LitParam, ast.LitNamedParam: = truecaseast.LitNull:// structural, ignoredefault:// A concrete literal property resolves at plan time -> not this case.returnfalse } }return}// countNeighbors counts a node's neighbors over dir restricted to types.func countNeighbors( graph.Graph, graph.NodeID, graph.Direction, []string) uint64 {varuint64iflen() == 0 {forrange .Neighbors(, ) { ++ }return }forrange .NeighborsByType(, , ) { ++ }return}
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.