funcs

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package funcs implements the built-in Cypher function registry.

Registry

DefaultRegistry is the pre-populated registry containing all essential built-ins. It implements expr.FunctionRegistry and is safe for concurrent use after construction.

Implementing built-ins

Each function follows the expr.BuiltinFn signature:

func(args []expr.Value) (expr.Value, error)

Type errors are returned as typed TypeError values rather than propagated as Go errors, unless the error is truly fatal (impossible with well-formed arguments). NULL arguments propagate according to each function's documented NULL-handling behaviour.

Concurrency

The registry is immutable after NewRegistry returns; all exported symbols are safe for concurrent use.

Index

Examples

Constants

View Source
const DefaultMaxCollectItems = 10_000_000

DefaultMaxCollectItems is the default upper bound on the number of values a single buffering aggregator (CollectAgg, PercentileContAgg, PercentileDiscAgg) will retain in one group before [Aggregator.Step] returns ErrCollectItemsExceeded.

Unlike the group-count cap enforced by EagerAggregation, this budget bounds the size of any one group's buffer. A grouping-key-free aggregate such as `RETURN collect(n)` produces exactly one group, so the group-count cap never fires; without a per-aggregator budget, `MATCH (n) RETURN collect(n)` would build an N-element list with no bound — exhausting memory and holding the graph's visibility barrier — on a sufficiently large graph.

The value matches the sibling pipeline-breaker caps (the engine's DefaultMaxResultRows and exec.DefaultMaxGroups / exec.DefaultMaxDistinct): high enough that ordinary queries — and the entire openCypher TCK — never reach it, yet finite so an unbounded scan fails fast with a typed error instead of an out-of-memory crash.

Variables

View Source
var DefaultRegistry = buildDefaultRegistry()

DefaultRegistry is the pre-populated registry containing all essential built-ins. It is safe for concurrent use.

View Source
var ErrCollectItemsExceeded = errors.New("funcs: aggregator per-group element budget exceeded")

ErrCollectItemsExceeded is returned by [Aggregator.Step] when a buffering aggregator's per-group element count exceeds its configured budget. It is the aggregator-level analogue of the group-count cap enforced by EagerAggregation.

Functions

func ClearStatementNow

func ClearStatementNow()

ClearStatementNow removes the frozen "now" so subsequent calls to StatementNow fall back to time.Now().

func SetStatementNow

func SetStatementNow(t time.Time)

SetStatementNow installs t as the statement-frozen "now" for every subsequent temporal "now" constructor in this process until ClearStatementNow is called.

func StatementNow

func StatementNow() time.Time

StatementNow returns the statement-frozen instant when one has been installed via SetStatementNow, otherwise time.Now().UTC(). The temporal "now" constructors call this in place of time.Now() so repeated calls within the same statement observe the same instant.

Types

type Aggregator

type Aggregator interface {
	// Init resets the aggregator to its initial (empty) state. Called once per
	// group before any Step calls for that group.
	Init()

	// Step incorporates a single input value into the running accumulation.
	// NULL handling is defined per aggregator (most skip NULLs).
	//
	// Step returns a non-nil error when the input cannot be accepted without
	// violating a resource bound — specifically, a buffering aggregator returns
	// [ErrCollectItemsExceeded] once its per-group element budget is exceeded.
	// The streaming aggregators hold O(1) state and always return nil. A
	// non-nil error aborts the enclosing aggregation: the caller must propagate
	// it rather than continue stepping.
	Step(v expr.Value) error

	// Result returns the final aggregated value for the group. It must be called
	// exactly once after all Step calls for the group, and before any reuse.
	Result() expr.Value
}

Aggregator accumulates values from a single aggregate column across multiple input rows within one group.

Lifecycle: Init → Step (once per row) → Result (once per group).

Aggregator is NOT safe for concurrent use.

type AggregatorFactory

type AggregatorFactory func() Aggregator

AggregatorFactory is a zero-argument constructor that returns a new, initialised Aggregator. EagerAggregation holds one factory per aggregate expression and calls it once per group.

func NewAvgAgg

func NewAvgAgg() AggregatorFactory

NewAvgAgg returns an AggregatorFactory for AvgAgg.

func NewCollectAgg

func NewCollectAgg() AggregatorFactory

NewCollectAgg returns an AggregatorFactory for CollectAgg using the default per-group element budget (DefaultMaxCollectItems).

func NewCollectAggN added in v0.2.0

func NewCollectAggN(limit int) AggregatorFactory

NewCollectAggN returns an AggregatorFactory for CollectAgg with an explicit per-group element budget. A positive limit is an active cap; zero disables the cap (the explicit opt-out). Callers thread the resolved budget here; the public zero-is-default ergonomic lives at the engine boundary.

func NewCountAgg

func NewCountAgg() AggregatorFactory

NewCountAgg returns an AggregatorFactory for CountAgg.

func NewCountStarAgg

func NewCountStarAgg() AggregatorFactory

NewCountStarAgg returns an AggregatorFactory for CountStarAgg.

func NewMaxAgg

func NewMaxAgg() AggregatorFactory

NewMaxAgg returns an AggregatorFactory for MaxAgg.

func NewMinAgg

func NewMinAgg() AggregatorFactory

NewMinAgg returns an AggregatorFactory for MinAgg.

func NewPercentileContAgg

func NewPercentileContAgg(p float64) AggregatorFactory

NewPercentileContAgg returns an AggregatorFactory for PercentileContAgg with the given percentile p (in [0.0, 1.0]) and the default per-group element budget (DefaultMaxCollectItems).

func NewPercentileContAggN added in v0.2.0

func NewPercentileContAggN(p float64, limit int) AggregatorFactory

NewPercentileContAggN returns an AggregatorFactory for PercentileContAgg with the given percentile p and an explicit per-group element budget. A positive limit is an active cap; zero disables it.

func NewPercentileDiscAgg

func NewPercentileDiscAgg(p float64) AggregatorFactory

NewPercentileDiscAgg returns an AggregatorFactory for PercentileDiscAgg with the given percentile p (in [0.0, 1.0]) and the default per-group element budget (DefaultMaxCollectItems).

func NewPercentileDiscAggN added in v0.2.0

func NewPercentileDiscAggN(p float64, limit int) AggregatorFactory

NewPercentileDiscAggN returns an AggregatorFactory for PercentileDiscAgg with the given percentile p and an explicit per-group element budget. A positive limit is an active cap; zero disables it.

func NewStdDevAgg

func NewStdDevAgg() AggregatorFactory

NewStdDevAgg returns an AggregatorFactory for StdDevAgg.

func NewStdDevPAgg

func NewStdDevPAgg() AggregatorFactory

NewStdDevPAgg returns an AggregatorFactory for StdDevPAgg.

func NewSumAgg

func NewSumAgg() AggregatorFactory

NewSumAgg returns an AggregatorFactory for SumAgg.

type ArityError

type ArityError struct {
	// Function is the name of the function.
	Function string
	// Got is the number of arguments received.
	Got int
	// Want is a human-readable description of the expected argument count.
	Want string
}

ArityError is returned when a built-in receives an unexpected number of arguments.

func (*ArityError) Error

func (e *ArityError) Error() string

Error implements the error interface.

type AvgAgg

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

AvgAgg computes the arithmetic mean of numeric inputs, skipping NULLs.

AvgAgg is NOT safe for concurrent use.

func (*AvgAgg) Init

func (a *AvgAgg) Init()

Init resets the accumulator.

func (*AvgAgg) Result

func (a *AvgAgg) Result() expr.Value

Result returns NULL if no non-NULL values were accumulated, otherwise a FloatValue representing the mean.

func (*AvgAgg) Step

func (a *AvgAgg) Step(v expr.Value) error

Step adds v to the running total, skipping NULLs and non-numeric values.

type CollectAgg

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

CollectAgg collects non-NULL values into an ordered expr.ListValue. The per-group element count is bounded by a budget (see DefaultMaxCollectItems); once exceeded, CollectAgg.Step returns ErrCollectItemsExceeded.

CollectAgg is NOT safe for concurrent use.

func (*CollectAgg) Init

func (a *CollectAgg) Init()

Init resets the collection.

func (*CollectAgg) Result

func (a *CollectAgg) Result() expr.Value

Result returns a expr.ListValue containing all accumulated non-NULL values, or an empty list if none were collected.

func (*CollectAgg) Step

func (a *CollectAgg) Step(v expr.Value) error

Step appends v to the collection if it is non-NULL. It returns ErrCollectItemsExceeded when the append would push the buffer past the configured budget, so the cap trips at the boundary rather than after the buffer has grown.

type CountAgg

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

CountAgg counts non-NULL input values. Corresponds to count(expr).

CountAgg is NOT safe for concurrent use.

func (*CountAgg) Init

func (a *CountAgg) Init()

Init resets the counter to zero.

func (*CountAgg) Result

func (a *CountAgg) Result() expr.Value

Result returns the count as an IntegerValue.

func (*CountAgg) Step

func (a *CountAgg) Step(v expr.Value) error

Step increments the counter for non-NULL values.

type CountStarAgg

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

CountStarAgg counts every input row regardless of NULLs. Corresponds to count(*).

CountStarAgg is NOT safe for concurrent use.

func (*CountStarAgg) Init

func (a *CountStarAgg) Init()

Init resets the counter to zero.

func (*CountStarAgg) Result

func (a *CountStarAgg) Result() expr.Value

Result returns the count as an IntegerValue.

func (*CountStarAgg) Step

func (a *CountStarAgg) Step(_ expr.Value) error

Step increments the counter unconditionally.

type MaxAgg

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

MaxAgg accumulates the maximum value across all non-NULL inputs using the openCypher total ordering defined by expr.Compare.

MaxAgg is NOT safe for concurrent use.

func (*MaxAgg) Init

func (a *MaxAgg) Init()

Init resets the accumulator to "no value seen".

func (*MaxAgg) Result

func (a *MaxAgg) Result() expr.Value

Result returns NULL if no non-NULL values were accumulated, otherwise the maximum value.

func (*MaxAgg) Step

func (a *MaxAgg) Step(v expr.Value) error

Step updates the maximum if v is non-NULL and greater than the current maximum.

type MinAgg

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

MinAgg accumulates the minimum value across all non-NULL inputs using the openCypher total ordering defined by expr.Compare.

MinAgg is NOT safe for concurrent use.

func (*MinAgg) Init

func (a *MinAgg) Init()

Init resets the accumulator to "no value seen".

func (*MinAgg) Result

func (a *MinAgg) Result() expr.Value

Result returns NULL if no non-NULL values were accumulated, otherwise the minimum value.

func (*MinAgg) Step

func (a *MinAgg) Step(v expr.Value) error

Step updates the minimum if v is non-NULL and less than the current minimum.

type PercentileContAgg

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

PercentileContAgg computes a percentile by linear interpolation (ANSI SQL PERCENTILE_CONT semantics). p must be in [0.0, 1.0]; it is clamped to that range. NULLs and non-numeric values are skipped.

Returns NULL if no non-NULL values were accumulated.

PercentileContAgg is NOT safe for concurrent use.

func (*PercentileContAgg) Init

func (a *PercentileContAgg) Init()

Init resets the accumulated values.

func (*PercentileContAgg) Result

func (a *PercentileContAgg) Result() expr.Value

Result sorts the values and applies linear interpolation. Returns NULL if the list is empty.

func (*PercentileContAgg) Step

func (a *PercentileContAgg) Step(v expr.Value) error

Step appends v to the list, skipping NULLs and non-numerics. It returns ErrCollectItemsExceeded when the append would push the buffer past the configured budget.

type PercentileDiscAgg

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

PercentileDiscAgg computes a percentile by choosing the nearest discrete value in the sorted set (ANSI SQL PERCENTILE_DISC semantics). p must be in [0.0, 1.0]; it is clamped to that range. NULLs and non-numeric values are skipped.

Returns NULL if no non-NULL values were accumulated.

PercentileDiscAgg is NOT safe for concurrent use.

func (*PercentileDiscAgg) Init

func (a *PercentileDiscAgg) Init()

Init resets the accumulated values.

func (*PercentileDiscAgg) Result

func (a *PercentileDiscAgg) Result() expr.Value

Result sorts the values and picks the element at the floor of p*(n-1). Returns NULL if the list is empty. When every input was IntegerValue, the result is also IntegerValue (PERCENTILE_DISC preserves the representation of the chosen element).

func (*PercentileDiscAgg) Step

func (a *PercentileDiscAgg) Step(v expr.Value) error

Step appends v to the list, skipping NULLs and non-numerics. It returns ErrCollectItemsExceeded when the append would push the buffer past the configured budget.

type Registry

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

Registry maps lower-cased function names to their implementations. It is immutable after NewRegistry returns; safe for concurrent reads.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty registry. Use DefaultRegistry to obtain the pre-populated built-in registry.

func (*Registry) Register

func (r *Registry) Register(name string, fn expr.BuiltinFn)

Register adds fn under the given name (stored lower-cased). Panics on duplicate; this is a programming error, not a runtime condition.

func (*Registry) Resolve

func (r *Registry) Resolve(name string) (expr.BuiltinFn, bool)

Resolve implements expr.FunctionRegistry.

Example

ExampleRegistry_Resolve resolves the built-in toUpper from DefaultRegistry and invokes it. Lookup is case-insensitive: names are lower-cased before resolution, so "toUpper" and "toupper" reach the same implementation.

package main

import (
	"fmt"

	"github.com/FlavioCFOliveira/GoGraph/cypher/expr"
	"github.com/FlavioCFOliveira/GoGraph/cypher/funcs"
)

func main() {
	fn, ok := funcs.DefaultRegistry.Resolve("toupper")
	if !ok {
		fmt.Println("toupper not registered")
		return
	}

	out, err := fn([]expr.Value{expr.StringValue("hello")})
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// out is a StringValue; print its raw text rather than the quoted String().
	fmt.Println(string(out.(expr.StringValue)))
}
Output:
HELLO
Example (Unknown)

ExampleRegistry_Resolve_unknown shows the not-found path: Resolve reports false for a name that is not registered.

package main

import (
	"fmt"

	"github.com/FlavioCFOliveira/GoGraph/cypher/funcs"
)

func main() {
	_, ok := funcs.DefaultRegistry.Resolve("no_such_function")
	fmt.Println("found:", ok)
}
Output:
found: false

type StdDevAgg

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

StdDevAgg computes the sample standard deviation using Welford's numerically stable online algorithm. NULLs and non-numeric values are skipped.

Returns NULL if fewer than 2 non-NULL values were accumulated (sample std dev of a single value is undefined). Returns 0.0 for exactly 2 identical values.

StdDevAgg is NOT safe for concurrent use.

func (*StdDevAgg) Init

func (a *StdDevAgg) Init()

Init resets the accumulator.

func (*StdDevAgg) Result

func (a *StdDevAgg) Result() expr.Value

Result returns NULL if n < 2, otherwise FloatValue(sqrt(M2/(n-1))).

func (*StdDevAgg) Step

func (a *StdDevAgg) Step(v expr.Value) error

Step incorporates v via Welford's online update, skipping NULLs.

type StdDevPAgg

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

StdDevPAgg computes the population standard deviation using Welford's numerically stable online algorithm. NULLs and non-numeric values are skipped. Returns NULL if no non-NULL values were accumulated.

StdDevPAgg is NOT safe for concurrent use.

func (*StdDevPAgg) Init

func (a *StdDevPAgg) Init()

Init resets the accumulator.

func (*StdDevPAgg) Result

func (a *StdDevPAgg) Result() expr.Value

Result returns NULL if n == 0, otherwise FloatValue(sqrt(M2/n)).

func (*StdDevPAgg) Step

func (a *StdDevPAgg) Step(v expr.Value) error

Step incorporates v via Welford's online update, skipping NULLs.

type SumAgg

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

SumAgg accumulates a numeric sum. Integer-only inputs produce an integer result; any float input causes the result to be a float.

SumAgg is NOT safe for concurrent use.

func (*SumAgg) Init

func (a *SumAgg) Init()

Init resets the accumulator.

func (*SumAgg) Result

func (a *SumAgg) Result() expr.Value

Result returns NULL if no non-NULL values were accumulated, otherwise the sum as IntegerValue or FloatValue.

func (*SumAgg) Step

func (a *SumAgg) Step(v expr.Value) error

Step adds v to the running sum, skipping NULLs. Promotes to float on the first FloatValue encountered.

type TypeError

type TypeError struct {
	// Function is the name of the function that encountered the type error.
	Function string
	// ArgIndex is the 0-based index of the offending argument.
	ArgIndex int
	// Got is the kind of the offending argument.
	Got expr.Kind
	// Want is a human-readable description of the expected type.
	Want string
}

TypeError is returned by built-in functions when an argument has the wrong type for the operation requested.

func (*TypeError) Error

func (e *TypeError) Error() string

Error implements the error interface.

Jump to

Keyboard shortcuts

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