sulpher

package
v0.27.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 4, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AlgBFS algHint = iota
	AlgDFS
)
View Source
const (
	ErrJobNotFound    = jobError("job not found")
	ErrJobNotComplete = jobError("job not completed")
)

Variables

View Source
var (
	ErrVisitedNodeLimit = errors.New("graph visited node limit exceeded")
	ErrResultLimit      = errors.New("graph result limit exceeded")
)

Sentinel errors for graph query limit violations.

Functions

This section is empty.

Types

type Algorithm

type Algorithm string

Algorithm represents the traversal algorithm hint. Kept for backward compatibility; the direct AST path defaults to BFS.

const (
	BFS Algorithm = "BFS"
	DFS Algorithm = "DFS"
)

type AlgorithmHint

type AlgorithmHint struct {
	Algorithm Algorithm
}

AlgorithmHint carries the optional traversal algorithm preference extracted from a Sulpher query prefix. It is passed to the executor alongside the AST.

type EntityGetter

type EntityGetter interface {
	Get(ctx context.Context, entity string, id int) (map[string]interface{}, error)
}

EntityGetter is the narrow store interface required by the Executor for property hydration. Any storage.Store satisfies this interface, but test mocks only need to implement Get rather than the full storage.Store.

type Env

type Env map[string]interface{}

Env is the execution environment for a single query result row. Variable names map to their current bound values.

Node values use lazy hydration: a node freshly bound from the graph carries only {"_nodeID": "entity:id"}. On first property access the executor calls hydrateNodeData which writes all store fields into the same map in place. Subsequent accesses are free.

Path values carry {"nodes": []interface{}, "relationships": []interface{}, "length": int}. Endpoint variables (a, b in MATCH p = shortestPath((a)-(b))) are additionally bound as node values.

type Executor

type Executor struct {
	// contains filtered or unexported fields
}

Executor executes Sulpher queries against a graph

func NewExecutor

func NewExecutor(g graph.Graph, maxDepth int) *Executor

NewExecutor creates a new query executor with no tenant scoping.

func NewExecutorForTenant

func NewExecutorForTenant(g graph.Graph, maxDepth int, tenantPrefix string) *Executor

NewExecutorForTenant creates a query executor scoped to a specific tenant. tenantPrefix is the XXXX@ prefix string for the tenant (e.g. "0001@"). The executor will only traverse nodes belonging to this tenant, and will return node IDs with the prefix stripped (i.e. client-facing "entity:id" format).

func (*Executor) Execute

func (e *Executor) Execute(ctx context.Context, query *sulpherast.Query, hint *AlgorithmHint) (*QueryResult, error)

Execute runs a parsed query and returns results. The context is checked during traversal; if cancelled, the query stops and returns an error rather than continuing to consume resources. Execute executes a parsed Cypher query using the executor's default max depth.

func (*Executor) ExecuteWithDepth

func (e *Executor) ExecuteWithDepth(ctx context.Context, query *sulpherast.Query, hint *AlgorithmHint, maxDepth int) (*QueryResult, error)

ExecuteWithDepth executes a Cypher query with an explicit maxDepth override. If maxDepth <= 0 the executor's default is used.

func (*Executor) SetLimits

func (e *Executor) SetLimits(limits GraphLimits)

SetLimits configures graph query execution limits.

func (*Executor) WithGraphStore

func (e *Executor) WithGraphStore(s GraphQueryable) *Executor

WithGraphStore attaches a graph-query-capable store for SQL push-down. When set, queries over adapted entities with translatable WHERE clauses are executed as a single SQL JOIN chain rather than an in-memory traversal. The store must be scoped to the same tenant as the executor.

func (*Executor) WithLogger

func (e *Executor) WithLogger(l zerolog.Logger) *Executor

WithLogger attaches a logger to the executor. The logger is used to emit WARN-level alerts when cross-tenant node IDs are detected in query results.

func (*Executor) WithStore

func (e *Executor) WithStore(s EntityGetter) *Executor

WithStore attaches a storage backend to the executor. When set, property conditions in WHERE clauses and inline node patterns are evaluated against the full entity data fetched from the store, not just the topology-derived "type" and "id" keys. The store should be scoped to the same tenant as the executor (i.e. already constructed with the matching TenantID).

type GraphLimits

type GraphLimits struct {
	MaxVisitedNodes int // Max nodes visited during traversal (0 = default 10000)
	MaxResults      int // Max result paths returned (0 = no limit)
}

GraphLimits holds server-enforced limits for graph query execution.

type GraphQueryable

type GraphQueryable interface {
	storage.AggregateQueryable
	// GraphEdgesTable returns the tenant-scoped edge table name,
	// e.g. "graph_t0000" for tenant 0, "graph_t0001" for tenant 1.
	GraphEdgesTable() string
}

GraphQueryable is the narrow interface the Sulpher executor needs for SQL push-down of graph traversal queries. It extends AggregateQueryable with the edge table name for this executor's tenant scope.

Any storage.SQLiteStore satisfies this via WithGraphStore; the server constructs a thin adapter when wiring the executor.

type Job

type Job struct {
	ID        string       `json:"id"`
	Query     string       `json:"query"`
	Status    JobStatus    `json:"status"`
	Result    *QueryResult `json:"result,omitempty"`
	Error     string       `json:"error,omitempty"`
	CreatedAt time.Time    `json:"created_at"`
	StartedAt *time.Time   `json:"started_at,omitempty"`
	EndedAt   *time.Time   `json:"ended_at,omitempty"`
	MaxDepth  int          `json:"max_depth"`
}

Job represents an async query job

type JobManager

type JobManager struct {
	// contains filtered or unexported fields
}

JobManager manages async query jobs

func NewJobManager

func NewJobManager(executor *Executor, ttl time.Duration) *JobManager

NewJobManager creates a new job manager

func (*JobManager) ExecuteSync

func (jm *JobManager) ExecuteSync(ctx context.Context, queryStr string, maxDepth int) (*QueryResult, error)

ExecuteSync executes a query synchronously

func (*JobManager) GetJob

func (jm *JobManager) GetJob(id string) (Job, bool)

GetJob retrieves a job by ID

func (*JobManager) GetJobResult

func (jm *JobManager) GetJobResult(id string) (*QueryResult, error)

GetJobResult retrieves the result of a completed job

func (*JobManager) SetLimits

func (jm *JobManager) SetLimits(limits GraphLimits)

SetLimits configures graph query execution limits on the underlying executor.

func (*JobManager) SetQueryTimeout

func (jm *JobManager) SetQueryTimeout(d time.Duration)

SetQueryTimeout sets the maximum execution time for async graph queries.

func (*JobManager) Submit

func (jm *JobManager) Submit(queryStr string, maxDepth int) (*Job, error)

Submit submits a new query job and returns immediately

type JobStatus

type JobStatus string

JobStatus represents the status of a query job

const (
	StatusPending   JobStatus = "pending"
	StatusRunning   JobStatus = "running"
	StatusCompleted JobStatus = "completed"
	StatusFailed    JobStatus = "failed"
)

type Operator

type Operator string

Operator represents a comparison operator used in WHERE conditions and SQL push-down generation.

const (
	OpEq  Operator = "="
	OpNe  Operator = "!="
	OpLt  Operator = "<"
	OpGt  Operator = ">"
	OpLte Operator = "<="
	OpGte Operator = ">="
)

type Parser

type Parser struct{}

Parser parses Sulpher queries using the github.com/ha1tch/sulpher Cypher parser. Parse now returns *sulpherast.Query directly; the bridge layer is no longer used.

func NewParser

func NewParser() *Parser

NewParser creates a new Sulpher parser.

func (*Parser) Parse

func (p *Parser) Parse(query string) (*sulpherast.Query, *AlgorithmHint, error)

Parse parses a Sulpher query string and returns the Cypher AST.

Algorithm hints can be specified in two ways:

  1. Preferred: a leading comment before the MATCH keyword: // sulpher.algorithm: dfs MATCH (u:User)-[:FOLLOWS]->(f) RETURN f

  2. Legacy (deprecated): a bare keyword prefix: DFS MATCH (u:User)-[:FOLLOWS]->(f) RETURN f

The hint is case-insensitive. If absent, BFS is used.

type QueryResult

type QueryResult struct {
	Data  []map[string]interface{} `json:"data"`
	Stats QueryStats               `json:"stats"`
}

QueryResult represents the result of a query execution

type QueryStats

type QueryStats struct {
	NodesTraversed int           `json:"nodes_traversed"`
	PathsFound     int           `json:"paths_found"`
	ExecutionTime  time.Duration `json:"execution_time_ms"`
}

QueryStats contains execution statistics

type RelDirection

type RelDirection int

RelDirection represents the direction of a relationship in a path pattern.

const (
	RelOutgoing      RelDirection = iota // -[r]->
	RelIncoming                          // <-[r]-
	RelBidirectional                     // -[r]-
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL