package graph

Import Path
	github.com/freeeve/gochickpeas/gql/internal/graph (on go.dev)

Dependency Relation
	imports 5 packages, and imported by 6 packages

Involved Source Files Package graph is the GQL engine's seam to the graph store: the portable read surface the planner and executor bind to (port of the Rust CypherGraph trait's data methods). Consumer-side interface per the DESIGN.md seam contract; *chickpeas.Snapshot (via New) is the one implementation. Deviations from the Rust trait, both deliberate: executor hooks (eval compilation, CALL/shortest-path offload) live with the executor behind the Native capability instead of on this interface, and inline-property parameters are resolved to runtime values by the caller at matcher-compile time instead of through thread-local scopes. Pre-resolved pattern matchers (port of the Rust NativeNodeMatcher / NativeRelMatcher): a node pattern's label and inline-property names are resolved to snapshot handles once per operator, so the per-candidate accept test is a bitmap contains plus a direct column read instead of interner lookups. SnapshotGraph adapts *chickpeas.Snapshot to the Graph seam, forwarding each method to the engine's read surface and resolving stored properties to runtime values. Engine scalar-type re-exports, so seam consumers (plan/eval/exec) can name node ids and directions without importing the engine package directly -- the interface remains the only coupling point.
Package-Level Type Names (total 8)
/* sort by: | */
Direction is the engine's traversal direction.
Graph is the minimal read surface the interpreter and the generic executor need. Methods returning *nodeset.Set return sets shared with the store's lazy indexes: callers must never mutate them (Clone first); a nil set reads as empty. AppendNeighborsByType is AppendNeighborsMatched with per-call name resolution (empty types match every type). AppendNeighborsMatched appends node's dir neighbors passing m to dst and returns the extended slice -- the batch form of NeighborsMatched for the executor's hot loops: an interface-returned iter.Seq cannot devirtualize, so ranging it heap-allocates its closures per call, while the batch form fills a caller-pooled buffer allocation-free. AppendRelationshipsMatched appends each traversed relationship's neighbor and CSR position to the parallel nodes/poss slices through a pre-resolved matcher (same devirtualization rationale as AppendNeighborsMatched). AvgDegree is the average degree over relType in dir -- a planner statistic used to break anchor ties; 0 when the type is unknown. AvgDegreeByLabel is AvgDegree conditioned on the node's label: the average number of relType rels in dir per node carrying label, zero-degree members included -- the hop fan-out a chain estimate multiplies when it knows what it stands on (a hub-heavy type inflates the global average for every label merely touching it). ok=false when the label is unknown (caller falls back to the global AvgDegree); a known label with no such rels is (0, true). ChainRootsVia returns the per-node forest-root array when an unbounded zero-minimum reachable expansion over types in dir, label-filtered by any of labels, provably collapses to a root lookup: exactly one type, functional in dir, with a label no non-terminal carries (both facts verified against the data and cached). ok=false means run the general walk. CompileNodeMatcher pre-resolves a node pattern's labels and inline {key: value} properties (params already resolved to values by the caller) into a reusable matcher, once per operator. CompileRelMatcher pre-resolves an expand's relationship-type names, once per operator: empty types match all; unknown names resolve to no match. CountNeighborsMatched counts the m-matched dir relationships from u to v -- the bound-both-endpoints probe, so an existence or multiplicity test never enumerates a candidate set. Equal to the number of times v appears in the matched dir expansion of u. Degree is node's untyped incident-relationship count in dir, O(1) per side -- a runtime fan-out signal for adaptive anchor decisions (which of two bound endpoints a probe should expand from). FullTextSearch is the boolean-AND full-text index scan behind CALL fts.search; ok=false means no full-text support. FunctionalVia reports whether the single type is functional in dir (at most one such rel per node) -- the reachable set of a functional type is the ancestor chain, walkable without frontier or dedup state. Verified against the data and cached. GeoWithinBBox is the bounding-box scan behind CALL geo.withinBBox (a box with minLon > maxLon crosses the antimeridian). GeoWithinRadius is the great-circle radius scan behind CALL geo.withinRadius; ok=false means no geo support. HasLabel reports whether node carries label. IDSpace is one past the largest id any node can take, so a dense 0..IDSpace() array indexed by node id never goes out of bounds. LabelCardinality is the number of nodes carrying label, from the label-index cardinality without materializing ids. LabelNames lists every label the graph defines (the labels() function composes per-node label lists from this plus HasLabel; label counts are small). Neighbors iterates node's neighbors over dir, any relationship type. NeighborsByType iterates node's neighbors over dir restricted to types (empty types match every type). NeighborsMatched is NeighborsByType through a pre-resolved matcher, skipping the per-call name resolution on hot paths. NodeCount is the number of distinct node ids -- a planner cardinality statistic, NOT the id-space size: under sparse ids it is smaller than IDSpace. Size dense node-indexed scratch by IDSpace, never this. NodeExists reports whether id is an actual node rather than a gap in a sparse id space: unconstrained scans and per-node result emission consult it so phantom ids never surface as rows. NodeMatcherAccepts reports whether node satisfies a compiled matcher -- every label present and every inline property equal, identical to HasLabel && NodePropEq over the same inputs. NodeProp reads a node's property as a runtime value (strings resolved); ok is false when absent. NodePropEq reports whether node's key property equals v. An absent property equals only a Null v (matching pattern-inline semantics); numerics coerce exactly like value.Compare. NodePropKeys is the property keys node carries a value for, in ascending key order (behind keys(n) / the n{.*} map projection). NodesWithLabel is the label scan's id set (shared; nil when the label is unknown). NodesWithProperty is the selectivity anchor behind {key: value} patterns: the nodes of label whose key equals v, from the inverted property index (shared set; nil when nothing matches or v is not an indexable scalar). RelEndpoints is the (source, target) of the relationship at CSR position pos, backing startNode(r)/endNode(r). RelProp reads a relationship's property (by outgoing-CSR position) as a runtime value; ok is false when absent. RelTypeAt is the type name of the relationship at CSR position pos, backing type(r); ok is a bounds guard only (every rel has one type). RelWeightReader is a hoisted relationship-weight reader for weighted shortest paths: reads the key weight by CSR position in O(1), defaulting to 1.0 when absent or non-numeric. nil when the key has no column at all -- the caller classifies that as unit weights. Relationships iterates each traversed relationship as (neighbor, csrPos); the position binds a rel variable and reads rel properties. RelationshipsMatched is Relationships through a pre-resolved matcher, skipping the per-call name resolution on hot paths. SubstringCandidates is a candidate superset for a STARTS WITH / ENDS WITH / CONTAINS anchor scan; ok=false means no index can help and the executor falls back to the label scan. Never false-negative. *SnapshotGraph func github.com/freeeve/gochickpeas/gql/internal/plan.Build(q *ast.Query, g Graph) (*plan.Plan, error) func github.com/freeeve/gochickpeas/gql/internal/plan.BuildWithInCols(q *ast.Query, inCols []string, g Graph) (*plan.Plan, error) func github.com/freeeve/gochickpeas/gql/internal/plan.Estimate(p *plan.Plan, g Graph) *plan.Estimates
Native is the capability a backend asserts to expose the full engine Snapshot for kernel offload (CALL procedures, shortest-path kernels, the columnar compiled eval path). The executor type-asserts Graph to Native; a backend without it falls back to the portable interpreter paths. ( Native) Snapshot() *chickpeas.Snapshot *SnapshotGraph
NodeID is the engine's node identifier.
NodeMatcher is a node pattern's labels and inline properties pre-resolved to snapshot handles. func Graph.CompileNodeMatcher(labels []string, props []PropSpec) *NodeMatcher func (*SnapshotGraph).CompileNodeMatcher(labels []string, props []PropSpec) *NodeMatcher func Graph.NodeMatcherAccepts(m *NodeMatcher, node chickpeas.NodeID) bool func (*SnapshotGraph).FilterMatchedTail(m *NodeMatcher, ids []chickpeas.NodeID, start int, rels []uint32, relStart int) ([]chickpeas.NodeID, []uint32) func (*SnapshotGraph).NodeMatcherAccepts(m *NodeMatcher, node chickpeas.NodeID) bool
PropSpec is one inline {key: value} predicate of a node pattern, with any parameter already resolved to its runtime value. A Null value matches only nodes missing the property. Key string Val value.Value func Graph.CompileNodeMatcher(labels []string, props []PropSpec) *NodeMatcher func (*SnapshotGraph).CompileNodeMatcher(labels []string, props []PropSpec) *NodeMatcher
RelMatcher is an expand's relationship types pre-resolved to interned ids. Wraps the engine's RelMatch, which has the exact semantics the seam needs: no types matches all, unknown names drop, all-unknown matches nothing. func Graph.CompileRelMatcher(types []string) *RelMatcher func (*SnapshotGraph).CompileRelMatcher(types []string) *RelMatcher func Graph.AppendNeighborsMatched(dst []chickpeas.NodeID, node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) []chickpeas.NodeID func Graph.AppendRelationshipsMatched(nodes []chickpeas.NodeID, poss []uint32, node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) ([]chickpeas.NodeID, []uint32) func Graph.CountNeighborsMatched(u, v chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) int func Graph.NeighborsMatched(node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) iter.Seq[chickpeas.NodeID] func Graph.RelationshipsMatched(node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) iter.Seq2[chickpeas.NodeID, uint32] func (*SnapshotGraph).AppendNeighborsMatched(dst []chickpeas.NodeID, node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) []chickpeas.NodeID func (*SnapshotGraph).AppendRelationshipsMatched(nodes []chickpeas.NodeID, poss []uint32, node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) ([]chickpeas.NodeID, []uint32) func (*SnapshotGraph).AppendRelsBetween(poss []uint32, u, v chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) []uint32 func (*SnapshotGraph).CountNeighborsMatched(u, v chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) int func (*SnapshotGraph).NeighborsMatched(node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) iter.Seq[chickpeas.NodeID] func (*SnapshotGraph).RelationshipsMatched(node chickpeas.NodeID, dir chickpeas.Direction, m *RelMatcher) iter.Seq2[chickpeas.NodeID, uint32]
SnapshotGraph is the native Graph implementation over an immutable engine snapshot. AppendNeighborsByType appends node's dir neighbors over types to dst, resolving the type match once and delegating to the core append accessor so the fill stays allocation-free (the iter.Seq form escapes a per-call yield closure across the package boundary). AppendNeighborsMatched appends one entry per matching dir relationship of node in CSR order (per-rel multiplicity -- pattern-match row semantics), delegating to the core AppendNeighborsEach so the fill stays allocation-free across the package boundary (the iter.Seq form would escape a per-call yield closure to the heap). The engine's deduped-ascending neighbor-ID set contract lives on Snapshot.AppendNeighborsMatch, which the executor deliberately does not use. AppendRelationshipsMatched appends traversed relationships' neighbors and CSR positions to the parallel nodes/poss slices through a pre-resolved matcher, skipping the per-call type-name resolution on hot walk paths (the core iterator is a thin inlinable closure constructor, so the range stays allocation-free). AppendRelsBetween appends the stored CSR positions of each m-matched dir relationship between u and v to poss (multiplicity preserved), scanning the lower-degree endpoint -- the bound-pair position seek that lets a named-rel rebind expand skip enumerating the from-node's whole degree. AvgDegree forwards the engine's per-type degree statistic. AvgDegreeByLabel forwards the engine's label-conditional degree statistic. ChainRootsVia resolves the chain-collapse capability through the core structural checks: one rel type, tried against each candidate label. CompileNodeMatcher resolves each label to its membership test (the engine's dense word bitmap when the label has one, the node set otherwise) and each inline key to its column once, so the per-candidate NodeMatcherAccepts avoids re-interning constant names. CompileRelMatcher pre-resolves relationship-type names via the engine's Match (empty = all, unknown names drop, all-unknown = none). CountNeighborsMatched counts u's m-matched dir relationships to v via the core degree-adaptive probe. Degree forwards the O(1) untyped incident-relationship count. FilterMatchedTail compacts ids[start:] in place to the matcher-accepted entries and returns the shortened slice; rels, when non-nil, is a parallel array compacted identically from relStart. Result-identical to testing each candidate with NodeMatcherAccepts -- the batch form exists so a whole expansion tail filters through one call, with the dominant matcher shape (one dense label, no inline properties) reduced to a hoisted word-bitmap loop: no per-candidate dispatch at all. Set-backed labels keep the per-candidate test, whose adaptive densification then upgrades later batches. FullTextSearch serves the boolean-AND token scan from the engine's lazy BM25 field index. FunctionalVia resolves the single-type functionality check. GeoWithinBBox serves the bounding-box scan from the engine's geo index. GeoWithinRadius serves the great-circle radius scan from the engine's lazy k-d tree index. HasLabel reports whether node carries label. IDSpace is the CSR id-space upper bound (exceeds NodeCount under sparse ids). LabelCardinality answers from the label index without materializing ids. LabelNames lists the graph's labels. Neighbors iterates node's neighbors over dir, any type. NeighborsByType iterates node's neighbors over dir restricted to types. NeighborsMatched iterates through a pre-resolved matcher. NodeCount is the number of distinct node ids. NodeExists forwards the engine's existence oracle. NodeMatcherAccepts reports whether node carries every label and matches every inline property of the compiled matcher. NodeProp reads a node property as a runtime value; ok is false when absent (including the engine's empty-string-means-missing convention). NodePropEq compares a stored node property against v: absent equals only Null; present values compare with value.Equal's coercion. NodePropKeys is the node's populated property keys in ascending order. NodesWithLabel is the shared label-index set; nil when the label is unknown. NodesWithProperty serves the {key: value} anchor from the engine's lazy inverted property index, dispatched on the value's scalar kind. A non-scalar value (or a string absent from the interner) matches nothing. RelEndpoints is the (source, target) of the relationship at pos. RelProp reads a relationship property (by CSR position) as a runtime value; ok is false when absent. RelTypeAt is the type name of the relationship at pos. RelWeightReader hoists the weight column once per search: the returned reader answers 1.0 for an absent or non-numeric weight, matching the per-rel property fallback. A key with NO column at all returns nil -- every edge would read 1.0, making the weighted search a unit-weight Dijkstra, so the caller must classify that case as unit weights and take the BFS dispatch (the third degraded shape of the constant-cost bug: the unit Dijkstra coming back through the property door). Relationships iterates traversed relationships as (neighbor, csrPos). RelationshipsMatched iterates traversed relationships as (neighbor, csrPos) through a pre-resolved matcher, skipping the per-call type-name resolution Relationships pays. Snapshot exposes the underlying engine snapshot (the Native capability for kernel offload and the columnar compiled eval path). SubstringCandidates: the native backend keeps its scan-filter (no trigram index), matching the Rust native default. *SnapshotGraph : Graph *SnapshotGraph : Native func New(g *chickpeas.Snapshot) *SnapshotGraph
Package-Level Functions (only one)
New wraps an engine snapshot as a Graph.
Package-Level Constants (total 3)
Direction values.
Direction values.
Direction values.