Documentation
¶
Overview ¶
Package cypher provides the public query engine API for the GoGraph Cypher executor.
Usage ¶
g := lpg.New[string, float64](adjlist.Config{})
// ... populate graph ...
engine := cypher.NewEngine(g)
result, err := engine.Run(ctx, "MATCH (n) RETURN n", nil)
if err != nil { ... }
defer result.Close()
for result.Next() {
rec := result.Record()
_ = rec
}
Plan cache ¶
Engine caches parsed and translated logical plans together with the semantic-analysis verdict in a bounded LRU keyed by the query string. The cached entry is a *planCacheEntry; the physical build step runs per Engine.Run call so that per-call executor state is fresh. Semantically invalid queries are also cached (with the typed error) so that repeated runs of the same bad query short-circuit without re-parsing.
The default capacity is DefaultPlanCacheCapacity (1024 entries). Configure a different bound via [EngineOptions.PlanCacheCapacity] and the NewEngineWithOptions constructor. Eviction is least-recently-used and emits the cypher.plan_cache.evictions counter on the global metrics surface; hits and misses are reported under cypher.plan_cache.hits and cypher.plan_cache.misses.
Concurrency ¶
Engine is safe for concurrent use. Each Run call creates an independent physical operator tree. The plan cache itself serialises its structural updates on a single sync.Mutex; the cached *planCacheEntry is immutable once published, so callers operate on the returned pointer without further synchronisation.
Index ¶
- Constants
- Variables
- func BindParams(params map[string]any) (map[string]expr.Value, error)
- func BuildPlan(plan ir.LogicalPlan, walker nodeWalkerIface, labelSrc labelResolverIface, ...) (op exec.Operator, cols []string, err error)
- func BuildPlanWithMutator(plan ir.LogicalPlan, walker nodeWalkerIface, labelSrc labelResolverIface, ...) (op exec.Operator, cols []string, err error)
- func QueryHasWritingClause(query string) bool
- type Engine
- func (e *Engine) ClearPlanCache()
- func (e *Engine) Explain(query string, params map[string]expr.Value) (string, error)
- func (e *Engine) Procs() *procs.Registry
- func (e *Engine) Run(ctx context.Context, query string, params map[string]expr.Value) (res *Result, err error)
- func (e *Engine) RunAny(ctx context.Context, query string, params map[string]any) (*Result, error)
- func (e *Engine) RunInTx(ctx context.Context, query string, params map[string]expr.Value) (res *Result, err error)
- func (e *Engine) RunInTxAny(ctx context.Context, query string, params map[string]any) (*Result, error)
- type EngineOptions
- type Result
Examples ¶
Constants ¶
const DefaultPlanCacheCapacity = 1024
DefaultPlanCacheCapacity is the default upper bound on the number of entries held by an Engine's plan cache. Chosen so that a typical OLTP workload — the same hundreds of queries reissued by connection pools and ORMs — stays entirely in-cache without unbounded growth under high query-text churn (parameter-baked queries, ad-hoc analytics, fuzzed input).
Configure a different capacity via [EngineOptions.PlanCacheCapacity]; pass 0 to use the default, or a positive integer to override. A negative value is rejected at constructor time as a configuration error.
Variables ¶
var ErrInternalPanic = errors.New("cypher: internal panic")
ErrInternalPanic wraps a recoverable panic that occurred while planning or executing a query on behalf of a single caller. The engine's query entrypoints (Engine.Run, Engine.RunInTx, Engine.RunAny, Engine.RunInTxAny) install a recover boundary so that such a panic — an index-out-of-range on a malformed plan, a nil dereference, a future bug — is converted into this error and returned to the caller instead of unwinding past the engine and crashing the embedding process. Callers may match it with errors.Is.
The returned error deliberately carries only the panic value, never a stack trace: the full trace (via runtime/debug.Stack) is logged to the default slog handler so internal details are not leaked to the caller. This is defence-in-depth against recoverable panics; a Go fatal runtime error (an uncatchable stack overflow) cannot be intercepted here and is instead prevented upstream by the parser's length/nesting guards.
var ErrResultRowsExceeded = errors.New("cypher: result row limit exceeded")
ErrResultRowsExceeded is returned by Result.Next and Result.Err when the number of materialised rows exceeds [EngineOptions.MaxResultRows]. It is a permanent error: once set, subsequent Next calls return false.
Functions ¶
func BindParams ¶
BindParams converts a map[string]any to map[string]expr.Value using the following type mapping:
- nil → expr.Null
- bool → expr.BoolValue
- int, int8, int16, int32, int64 → expr.IntegerValue
- uint, uint8, uint16, uint32, uint64 → expr.IntegerValue (truncated to int64)
- float32, float64 → expr.FloatValue
- string → expr.StringValue
- []any → expr.ListValue (recursively converted)
- map[string]any → expr.MapValue (recursively converted)
- expr.Value → passed through unchanged
Returns an error for unsupported types.
Example ¶
ExampleBindParams converts a map of Go values into the engine's internal parameter representation. Engine.RunAny calls this for you; BindParams is exported for callers that bind once and run a query repeatedly.
package main
import (
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
)
func main() {
bound, err := cypher.BindParams(map[string]any{
"name": "acme",
"size": int64(42),
})
if err != nil {
fmt.Println("error:", err)
return
}
_, hasName := bound["name"]
_, hasSize := bound["size"]
fmt.Printf("bound=%d name=%v size=%v\n", len(bound), hasName, hasSize)
}
Output: bound=2 name=true size=true
func BuildPlan ¶
func BuildPlan( plan ir.LogicalPlan, walker nodeWalkerIface, labelSrc labelResolverIface, reg expr.FunctionRegistry, params map[string]expr.Value, ) (op exec.Operator, cols []string, err error)
BuildPlan converts an IR ir.LogicalPlan tree into a physical exec.Operator tree together with the ordered output column names.
walker provides node enumeration; labelSrc provides label-filtered scans; reg provides the built-in function registry; params are the query parameters.
Sprint 25 support matrix:
- ir.AllNodesScan
- ir.NodeByLabelScan
- ir.Selection (predicate is an always-true stub)
- ir.Projection
- ir.ProduceResults (required as root)
- ir.Expand (stub; child rows pass through, rel/dst vars bound to NULL)
func BuildPlanWithMutator ¶
func BuildPlanWithMutator( plan ir.LogicalPlan, walker nodeWalkerIface, labelSrc labelResolverIface, reg expr.FunctionRegistry, params map[string]expr.Value, mutator exec.GraphMutator, ) (op exec.Operator, cols []string, err error)
BuildPlanWithMutator converts an IR ir.LogicalPlan tree into a physical exec.Operator tree, supporting both read and write IR operators. The mutator provides the write surface for CREATE, SET, REMOVE, DELETE, and MERGE operators.
For read-only plans the behaviour is identical to BuildPlan; the mutator is only invoked when a write IR node is encountered.
func QueryHasWritingClause ¶
QueryHasWritingClause reports whether the query string contains any writing keyword (CREATE, MERGE, SET, REMOVE, DELETE, DETACH) outside a DDL prefix, i.e. whether it must be routed through Engine.RunInTx rather than Engine.Run. This is a textual heuristic: it avoids triggering the plan-cache machinery on a second pass, which would otherwise double-count hits and misses in concurrency tests.
External front-ends that classify queries as read vs write (for example, to serialise writers or pick a read replica) should call this rather than re-deriving the keyword set, so the classification stays in lockstep with Engine.RunAny.
The heuristic is intentionally permissive — false positives (writing keywords inside string literals or backtick identifiers) merely cause a read-only query to be routed through RunInTx, which executes identical semantics with the same correctness guarantees, only with the cost of opening and committing a write transaction.
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is the public query engine. It binds a graph, a function registry, and a plan cache, and exposes a single Run method for query execution.
Engine is safe for concurrent use. A single Engine may serve any number of concurrent Engine.Run readers together with concurrent Engine.RunInTx writers: each call builds its own operator tree, the plan cache is internally synchronised, and both the physical-plan build and execution run under the graph's visibility barrier (lpg.Graph.View for reads, lpg.Graph.ApplyAtomically for writes). A writer that grows the node space can therefore never tear a concurrent reader's plan build, and readers never observe a partially-applied write transaction (#1077, audit gap F3).
Write queries remain subject to the underlying store's single-writer constraint: when the Engine is backed by a txn.Store, concurrent Engine.RunInTx calls serialise on the store's writer mutex.
func NewEngine ¶
NewEngine creates an Engine backed by g. The default built-in function registry (funcs.DefaultRegistry) and the default plan cache capacity (DefaultPlanCacheCapacity) are used. Use NewEngineWithOptions when a non-default function registry or plan cache capacity is required.
If g has no index.Manager attached yet, NewEngine installs a new empty one so that DDL statements (CREATE INDEX / DROP INDEX) work out of the box.
Example ¶
ExampleNewEngine shows the minimal setup: build an empty labelled property graph and bind it to an Engine ready to run queries.
package main
import (
"context"
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
"github.com/FlavioCFOliveira/GoGraph/graph/adjlist"
"github.com/FlavioCFOliveira/GoGraph/graph/lpg"
)
func main() {
g := lpg.New[string, float64](adjlist.Config{})
eng := cypher.NewEngine(g)
// A fresh engine over an empty graph runs queries that return no rows.
res, err := eng.Run(context.Background(), "MATCH (n) RETURN n", nil)
if err != nil {
fmt.Println("error:", err)
return
}
defer res.Close()
var rows int
for res.Next() {
rows++
}
fmt.Println("rows:", rows)
}
Output: rows: 0
func NewEngineWithOptions ¶
NewEngineWithOptions creates an Engine backed by g with explicit options. Zero-valued fields are filled with their documented defaults. When opts.Store is non-nil, the Engine is bound to that WAL-enabled txn.Store in addition to g.
If g has no index.Manager attached yet, a new empty one is installed.
func NewEngineWithRegistry ¶
NewEngineWithRegistry creates an Engine backed by g using a custom function registry and the default plan cache capacity.
If g has no index.Manager attached yet, a new empty one is installed.
func NewEngineWithStore ¶
NewEngineWithStore creates an Engine backed by a WAL-enabled txn.Store using the default plan cache capacity.
All write queries routed through Engine.RunInTx use a single txn.Tx for atomicity and WAL durability: mutations are applied eagerly to the in-memory graph (so reads within the same transaction see the writes) and the WAL is fsynced on Result.Close when no pipeline error occurred.
The underlying graph is taken from store.Graph(). If the graph has no index.Manager attached yet, a new empty one is installed.
func (*Engine) ClearPlanCache ¶
func (e *Engine) ClearPlanCache()
ClearPlanCache drops every cached plan and increments the cypher.plan_cache.invalidations counter exactly once. It is the operator-facing invalidation hook installed on every DDL operator (CREATE/DROP INDEX, CREATE/DROP CONSTRAINT) — successful schema mutations call it so that subsequent queries re-plan against the new index / constraint topology rather than reusing stale plans built before the schema changed.
ClearPlanCache is also safe to invoke directly as a user-facing manual reset (e.g. from operational tooling after an out-of-band index swap on the underlying graph).
ClearPlanCache is idempotent and safe for concurrent use; each call emits exactly one invalidations counter increment regardless of the cache's prior size.
func (*Engine) Explain ¶
Explain returns a textual representation of the physical plan that would be chosen to execute query with the given params. The plan reflects current index availability: a hash index on the relevant (label, property) pair causes the relevant Selection+LabelScan subtree to appear as NodeByIndexSeek. No rows are produced; the graph is not modified.
The format mirrors ir.Explain but annotates Selection→LabelScan pairs that would be rewritten to index seeks at execution time.
Example ¶
ExampleEngine_Explain returns the logical plan for a query as text without executing it or touching the graph.
package main
import (
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
"github.com/FlavioCFOliveira/GoGraph/graph/adjlist"
"github.com/FlavioCFOliveira/GoGraph/graph/lpg"
)
func main() {
g := lpg.New[string, float64](adjlist.Config{})
eng := cypher.NewEngine(g)
plan, err := eng.Explain("MATCH (n:Person) RETURN n", nil)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Print(plan)
}
Output: ProduceResults └─ Projection └─ NodeByLabelScan
func (*Engine) Procs ¶
Procs returns the engine's procedure registry so callers can register custom procedures alongside the built-in db.* set. The returned *procs.Registry is the live, owning registry — mutations are observed immediately by every subsequent CALL <ns>.<name>() in any query parsed by this engine.
Returned registry is non-nil. Safe for concurrent use; see procs.Registry for the concurrency contract.
func (*Engine) Run ¶
func (e *Engine) Run(ctx context.Context, query string, params map[string]expr.Value) (res *Result, err error)
Run parses, analyses, plans, and executes query, returning a materialised Result. The query is built and drained inside the read visibility barrier (Graph.View) so it observes a consistent, partial-transaction-free snapshot. DDL statements take a dedicated fast path. Parameters are bound from params and type-checked against the plan before execution.
If ctx is already cancelled or its deadline has elapsed when Run is called, it returns promptly — before any parse, plan, or execution work — with an error wrapping the context error (matchable via errors.Is against context.Canceled / context.DeadlineExceeded).
A recoverable panic raised while planning or executing the query is intercepted and returned as an error wrapping ErrInternalPanic; it never unwinds past this method to crash the embedding process.
Example ¶
ExampleEngine_Run runs a read query against a populated graph and reads a scalar aggregate from the streaming result. Result must always be closed.
package main
import (
"context"
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
"github.com/FlavioCFOliveira/GoGraph/graph/adjlist"
"github.com/FlavioCFOliveira/GoGraph/graph/lpg"
)
func main() {
g := lpg.New[string, float64](adjlist.Config{})
for _, key := range []string{"a", "b", "c"} {
if err := g.AddNode(key); err != nil {
fmt.Println("error:", err)
return
}
if err := g.SetNodeLabel(key, "Person"); err != nil {
fmt.Println("error:", err)
return
}
}
eng := cypher.NewEngine(g)
res, err := eng.Run(context.Background(), "MATCH (n:Person) RETURN count(n) AS people", nil)
if err != nil {
fmt.Println("error:", err)
return
}
defer res.Close()
for res.Next() {
rec := res.Record()
fmt.Println("people:", rec["people"])
}
}
Output: people: 3
func (*Engine) RunAny ¶
RunAny executes query with params expressed as map[string]any, automatically converting Go native types to expr.Value. See BindParams for the supported conversions.
RunAny auto-detects whether the query contains writing clauses (CREATE, MERGE, SET, REMOVE, DELETE, DETACH DELETE) and routes through Engine.RunInTx when so, or Engine.Run otherwise. Callers that need an explicit choice should invoke Engine.Run / Engine.RunInTx directly.
Example ¶
ExampleEngine_RunAny passes query parameters as a plain map[string]any, which the engine binds automatically. This is the convenient entry point for callers that do not want to import the internal value types.
package main
import (
"context"
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
"github.com/FlavioCFOliveira/GoGraph/graph/adjlist"
"github.com/FlavioCFOliveira/GoGraph/graph/lpg"
)
func main() {
g := lpg.New[string, float64](adjlist.Config{})
eng := cypher.NewEngine(g)
if _, err := drainTxAny(eng,
`CREATE (:Account {owner: "alice"}), (:Account {owner: "bob"})`); err != nil {
fmt.Println("seed error:", err)
return
}
// $owner is supplied as a Go string in the params map.
res, err := eng.RunAny(context.Background(),
`MATCH (a:Account) WHERE a.owner = $owner RETURN a.owner AS owner`,
map[string]any{"owner": "bob"},
)
if err != nil {
fmt.Println("error:", err)
return
}
defer res.Close()
for res.Next() {
fmt.Println("owner:", res.Record()["owner"])
}
}
// drainTxAny runs a write query in a transaction, draining and closing the
// result. It is a tiny helper shared by the parameter example above.
func drainTxAny(eng *cypher.Engine, query string) (int, error) {
res, err := eng.RunInTxAny(context.Background(), query, nil)
if err != nil {
return 0, err
}
defer res.Close()
var rows int
for res.Next() {
rows++
}
return rows, res.Err()
}
Output: owner: "bob"
func (*Engine) RunInTx ¶
func (e *Engine) RunInTx(ctx context.Context, query string, params map[string]expr.Value) (res *Result, err error)
RunInTx executes a write query against the engine's graph and returns a streaming Result. Unlike [Run], RunInTx inspects the IR plan for write operators; when any write operator is present it builds a mutator adapter so that write operators can modify the graph.
For the current in-memory implementation there is no external transaction manager (lpg.Graph does not support rollback). "Commit on success, rollback on error" means: the pipeline runs to completion with mutations applied eagerly; if any operator returns an error the pipeline is drained no further (standard Volcano error propagation) and the partial mutations remain in the graph. This matches the single-writer, in-memory contract documented in CLAUDE.md.
RunInTx is safe for concurrent use (each call creates an independent operator tree), subject to the single-writer constraint on write queries.
If ctx is already cancelled or its deadline has elapsed when RunInTx is called, it returns promptly — before any parse, plan, or txn.Store.Begin work — with an error wrapping the context error (matchable via errors.Is against context.Canceled / context.DeadlineExceeded).
Example ¶
ExampleEngine_RunInTx executes a CREATE inside a transaction (atomic and, for WAL-backed engines, durable) and then reads the data back in a second query.
package main
import (
"context"
"fmt"
"github.com/FlavioCFOliveira/GoGraph/cypher"
"github.com/FlavioCFOliveira/GoGraph/graph/adjlist"
"github.com/FlavioCFOliveira/GoGraph/graph/lpg"
)
func main() {
g := lpg.New[string, float64](adjlist.Config{})
eng := cypher.NewEngine(g)
// Write: CREATE two labelled nodes atomically.
write, err := eng.RunInTx(context.Background(),
`CREATE (:Account {owner: "alice"}), (:Account {owner: "bob"})`, nil)
if err != nil {
fmt.Println("write error:", err)
return
}
for write.Next() { //nolint:revive // a write query streams no result rows; drain then close
}
if err := write.Err(); err != nil {
fmt.Println("write error:", err)
return
}
write.Close()
// Read-back: the committed nodes are visible to a subsequent query.
read, err := eng.Run(context.Background(), "MATCH (a:Account) RETURN count(a) AS accounts", nil)
if err != nil {
fmt.Println("read error:", err)
return
}
defer read.Close()
for read.Next() {
fmt.Println("accounts:", read.Record()["accounts"])
}
}
Output: accounts: 2
func (*Engine) RunInTxAny ¶
func (e *Engine) RunInTxAny(ctx context.Context, query string, params map[string]any) (*Result, error)
RunInTxAny executes a write query with params expressed as map[string]any, automatically converting Go native types to expr.Value. See BindParams.
type EngineOptions ¶
type EngineOptions struct {
// Registry, when non-nil, overrides the default built-in function
// registry used to resolve scalar function calls.
Registry expr.FunctionRegistry
// Store, when non-nil, binds the Engine to a WAL-enabled
// [txn.Store]. The Engine's graph is taken from store.Graph()
// when both Store and Graph fields are set; the explicit Graph
// is then ignored. Run queries through [Engine.RunInTx] for
// atomicity and WAL durability.
Store *txn.Store[string, float64]
// PlanCacheCapacity bounds the number of cached plans. Zero
// selects [DefaultPlanCacheCapacity]; positive values override
// it. A negative value is treated as misconfiguration and is
// clamped to the default by the constructor.
PlanCacheCapacity int
// MaxResultRows, when positive, limits the number of rows a single
// [Engine.Run] or [Engine.RunInTx] call may materialise. If a query
// produces more rows than MaxResultRows, the [Result] iterator returns
// [ErrResultRowsExceeded] from [Result.Next] when the limit is hit, and
// [Result.Err] reports the same error. Zero means no limit.
//
// This circuit-breaker prevents unintentional Cartesian-product queries
// from exhausting available memory. Set it to a value appropriate for the
// operational environment (e.g. 1_000_000 for a shared multi-tenant server).
MaxResultRows int64
}
EngineOptions configures an Engine. The zero value is valid: it selects the default function registry (funcs.DefaultRegistry), no WAL-backed store, and the default plan cache capacity (DefaultPlanCacheCapacity). Use NewEngineWithOptions to construct an Engine from this struct.
type Result ¶
type Result struct {
// contains filtered or unexported fields
}
Result is a forward-only streaming result set returned by Engine.Run / Engine.RunInTx. It wraps exec.ResultSet and exposes the same iterator contract.
Lifecycle contract ¶
Every Result returned from a successful Run/RunInTx call MUST be closed by the caller via Result.Close, even if Result.Err is non-nil and even if the caller stops iterating before exhaustion. Close releases the physical operator tree, drains any goroutines spawned by parallel operators, commits or rolls back buffered index mutations for write queries, and (for WAL-backed engines) fsyncs the WAL or rolls the transaction back.
The typical pattern is:
res, err := engine.Run(ctx, query, params)
if err != nil {
return err
}
defer res.Close()
for res.Next() {
rec := res.Record()
// ... consume rec ...
}
return res.Err()
Safety net ¶
Result installs a runtime.SetFinalizer that detects callers who forget to Close. When the garbage collector reclaims an unclosed Result, the finalizer:
- Increments the metric "cypher.result.leaked" so operators see the incidence count in their monitoring; and
- Best-effort closes the underlying resources to limit damage on a long-running server.
The finalizer is a fail-stop diagnostic, NOT a substitute for an explicit Close. In particular, the finalizer runs at an unpredictable time after the leak (it depends on the GC schedule) and CANNOT report errors back to the caller. WAL-backed write transactions held open until finalisation still commit lazily — a window during which other writers may be blocked on the store mutex. Callers that need predictable resource release MUST call Close themselves.
Result is NOT safe for concurrent use.
func (*Result) Close ¶
Close releases all resources held by the result set. When the result was created by Engine.RunInTx, Close also:
- Commits or rolls back buffered index changes (always).
- When the engine is WAL-backed (NewEngineWithStore), WAL-syncs the buffered ops via txn.Tx.CommitWALOnly on success, or calls txn.Tx.Rollback on error. Mutations have already been applied to the in-memory graph eagerly; CommitWALOnly only persists them to the WAL.
Close is idempotent: a second invocation returns nil without re-entering the underlying ResultSet. The finalizer safety net also relies on this idempotence — see the type-level documentation.
func (*Result) Next ¶
Next advances to the next result row. Returns true when a row is available. If [EngineOptions.MaxResultRows] is set and the limit is reached, Next sets the result's error to ErrResultRowsExceeded and returns false.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ast defines the Abstract Syntax Tree (AST) for openCypher 9.
|
Package ast defines the Abstract Syntax Tree (AST) for openCypher 9. |
|
Package exec implements the Volcano-style executor for the Cypher query engine.
|
Package exec implements the Volcano-style executor for the Cypher query engine. |
|
Package explain renders Cypher execution plans as human-readable text (EXPLAIN mode) and instruments them with per-operator execution statistics (PROFILE mode).
|
Package explain renders Cypher execution plans as human-readable text (EXPLAIN mode) and instruments them with per-operator execution statistics (PROFILE mode). |
|
Package expr defines the runtime value model for the Cypher executor.
|
Package expr defines the runtime value model for the Cypher executor. |
|
Package funcs implements the built-in Cypher function registry.
|
Package funcs implements the built-in Cypher function registry. |
|
Package ir defines the logical plan intermediate representation (IR) for the Cypher query compiler.
|
Package ir defines the logical plan intermediate representation (IR) for the Cypher query compiler. |
|
rewrite
Package rewrite provides a rule-based logical-plan rewrite/optimisation framework for the Cypher IR.
|
Package rewrite provides a rule-based logical-plan rewrite/optimisation framework for the Cypher IR. |
|
Package parser translates the ANTLR4-generated Cypher parse tree into the typed AST defined in github.com/FlavioCFOliveira/GoGraph/cypher/ast.
|
Package parser translates the ANTLR4-generated Cypher parse tree into the typed AST defined in github.com/FlavioCFOliveira/GoGraph/cypher/ast. |
|
gen
Package gen contains the ANTLR4-generated lexer and parser for openCypher 9.
|
Package gen contains the ANTLR4-generated lexer and parser for openCypher 9. |
|
Package plan provides the cost-based planner for the Cypher executor.
|
Package plan provides the cost-based planner for the Cypher executor. |
|
Package procs defines the procedure registry for the Cypher executor.
|
Package procs defines the procedure registry for the Cypher executor. |
|
Package sema implements the scope-analysis pass for openCypher queries.
|
Package sema implements the scope-analysis pass for openCypher queries. |
|
Package tck records the conformance evolution of the GoGraph Cypher engine against the openCypher Technology Compatibility Kit.
|
Package tck records the conformance evolution of the GoGraph Cypher engine against the openCypher Technology Compatibility Kit. |