expr

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package expr defines the runtime value model for the Cypher executor.

Value model

A Value is a typed, immutable datum produced or consumed by an executor operator. Every value carries a Kind tag used by the planner and executor to dispatch without interface boxing in hot paths.

Three-valued logic (3VL)

NULL is a first-class singleton (Null). Comparisons involving NULL return NULL, not false, in accordance with openCypher 9 §4.1.3. Callers that need boolean truth must use IsTruthy.

Ordering

Compare implements the openCypher 9 total ordering for use in ORDER BY: NULLs sort last. Within a type the ordering matches Go's natural ordering. Across different non-null types the canonical sequence is:

Path < Node < Relationship < Map < List < String < Boolean < Float < Integer

Concurrency

All Value implementations are immutable after construction. Concurrent reads are safe without external locking.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Compare

func Compare(a, b Value) int

Compare returns -1, 0, or +1 following openCypher 9 ORDER BY semantics. NULLs sort after all non-null values. Values of different non-null types are ordered by kindOrder. Values of the same type use natural ordering.

Note: this is a total order for sorting purposes only; it does not replace [Value.Equal] for predicate evaluation.

func HashRow

func HashRow(row []Value) uint64

HashRow returns a uint64 hash that represents the ordered sequence of values in row. Two rows whose elements are pairwise equal (per openCypher equality semantics) will have the same hash. The inverse is not guaranteed — callers must verify equality after a hash match.

NULL values contribute their own hash (0) to the mix; they participate in grouping but never compare equal to any value including another NULL.

func IsNull

func IsNull(v Value) bool

IsNull reports whether v is the NULL singleton.

func IsTruthy

func IsTruthy(v Value) bool

IsTruthy returns true iff v is BoolValue(true). NULL and false both return false, matching Cypher predicate semantics.

Types

type BoolValue

type BoolValue bool

BoolValue is a Cypher boolean value (true or false). Note that Cypher's three-valued logic introduces a third truth state, NULL, which is not representable as BoolValue; use Null for that.

func (BoolValue) Equal

func (v BoolValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue per boolean equality otherwise.

func (BoolValue) Hash

func (v BoolValue) Hash() uint64

Hash implements Value.

func (BoolValue) Kind

func (v BoolValue) Kind() Kind

Kind implements Value.

func (BoolValue) String

func (v BoolValue) String() string

String returns "true" or "false".

type BuiltinFn

type BuiltinFn func(args []Value) (Value, error)

BuiltinFn is the signature of a built-in Cypher function.

type DateTimeValue

type DateTimeValue struct {
	// T carries date, time, and offset.
	T time.Time
}

DateTimeValue is a date + time + zone.

func AddDurationToDateTime

func AddDurationToDateTime(v DateTimeValue, d DurationValue) DateTimeValue

AddDurationToDateTime adds d to v, preserving v's zone.

func NewDateTime

func NewDateTime(y, mo, d, h, mi, s, ns int, loc *time.Location) DateTimeValue

NewDateTime constructs a DateTimeValue from components and a time.Location.

func ParseDateTime

func ParseDateTime(s string) (DateTimeValue, error)

ParseDateTime parses ISO-8601 zoned date-time: YYYY-MM-DDTHH:MM:SS[.frac][±HH:MM|Z]. A zone suffix is required. An optional trailing bracketed IANA zone name (e.g. "Europe/Stockholm") is honoured when time.LoadLocation resolves it; otherwise the numeric offset is used to build a fixed-zone location.

func SubDurationFromDateTime

func SubDurationFromDateTime(v DateTimeValue, d DurationValue) DateTimeValue

SubDurationFromDateTime is the inverse of AddDurationToDateTime.

func (DateTimeValue) Equal

func (v DateTimeValue) Equal(other Value) Value

Equal implements Value with 3VL semantics. Two DateTimeValues are equal iff they refer to the same instant; the textual zone is not considered.

func (DateTimeValue) Hash

func (v DateTimeValue) Hash() uint64

Hash implements Value.

func (DateTimeValue) Kind

func (v DateTimeValue) Kind() Kind

Kind implements Value.

func (DateTimeValue) String

func (v DateTimeValue) String() string

String renders ISO-8601 yyyy-mm-ddThh:mm:ss[.frac] followed by the zone offset (Z for UTC, +HH:MM otherwise).

type DateValue

type DateValue struct {
	// Year is the Gregorian year.
	Year int
	// Month is 1–12.
	Month int
	// Day is 1–31, bounded by the days in Month.
	Day int
}

DateValue is a calendar date (year/month/day) with no time-of-day and no time zone. The zero value (0001-01-01) is the proleptic Gregorian epoch matching Go's time.Time zero.

func AddDurationToDate

func AddDurationToDate(dv DateValue, d DurationValue) DateValue

AddDurationToDate adds d to dv with calendar-aware rules: months are applied first (clamping to month-end), then days, then sub-day components are dropped (Date has no sub-day component).

func DateFromTime

func DateFromTime(t time.Time) DateValue

DateFromTime builds a DateValue from the calendar date of t (in t's own location).

func NewDate

func NewDate(y, m, d int) DateValue

NewDate constructs a DateValue from y/m/d, normalising overflow via time.Date semantics (e.g. month 13 wraps to next year).

func ParseDate

func ParseDate(s string) (DateValue, error)

ParseDate parses an ISO-8601 date string. Accepted forms (calendar, week, ordinal):

YYYY-MM-DD, YYYYMMDD, YYYY-MM, YYYYMM, YYYY,
YYYY-Www-D, YYYYWwwD, YYYY-Www, YYYYWww,
YYYY-DDD, YYYYDDD.

Returns NULL-able semantics: callers receiving an error should treat the value as openCypher TYPE_ERROR (today: surfaced as expr.Null by the caller).

func SubDurationFromDate

func SubDurationFromDate(dv DateValue, d DurationValue) DateValue

SubDurationFromDate is the inverse of AddDurationToDate.

func (DateValue) Equal

func (v DateValue) Equal(other Value) Value

Equal implements Value with 3VL semantics.

func (DateValue) Hash

func (v DateValue) Hash() uint64

Hash implements Value.

func (DateValue) Kind

func (v DateValue) Kind() Kind

Kind implements Value.

func (DateValue) String

func (v DateValue) String() string

String renders the date in ISO-8601 extended form: YYYY-MM-DD.

func (DateValue) ToTime

func (v DateValue) ToTime() time.Time

ToTime returns the DateValue as a time.Time anchored at 00:00:00 UTC.

type DurationValue

type DurationValue struct {
	// Months is the number of whole months (may be negative).
	Months int64
	// Days is the number of whole days (may be negative).
	Days int64
	// Seconds is the number of whole seconds (may be negative).
	Seconds int64
	// Nanos is the sub-second component in [0, 999_999_999]; the sign is
	// carried entirely by Seconds for canonical form.
	Nanos int32
}

DurationValue is an ISO-8601 duration with four independent components. Months and days do not reduce to seconds; the executor applies them calendar-aware when added to a temporal value.

func AddDurations

func AddDurations(a, b DurationValue) DurationValue

AddDurations returns a new Duration that is the sum of a and b.

func DivDurationFloat

func DivDurationFloat(d DurationValue, k float64) DurationValue

DivDurationFloat divides d by k. Returns the zero duration when k is zero.

func MulDuration

func MulDuration(d DurationValue, k int64) DurationValue

MulDuration scales d by an integer factor.

func MulDurationFloat

func MulDurationFloat(d DurationValue, k float64) DurationValue

MulDurationFloat scales d by a floating-point factor. The result rounds fractional months/days into the seconds component using the same 30.4368750-day Gregorian-month approximation as ParseDuration.

Fractional nanoseconds (the smallest representable unit) are truncated toward zero — Java's `(long)` cast behaviour, matching the openCypher TCK convention for `duration * scalar` and `duration / scalar`. A half-nano result therefore disappears rather than rounding up: e.g. `duration({nanoseconds: 1}) / 2` yields zero nanoseconds, not 1.

func NegateDuration

func NegateDuration(d DurationValue) DurationValue

NegateDuration returns -d.

func NewDuration

func NewDuration(months, days, seconds int64, nanos int32) DurationValue

NewDuration normalises the components to canonical form (Nanos in [0, 999_999_999], sign carried by Seconds).

func ParseDuration

func ParseDuration(s string) (DurationValue, error)

ParseDuration parses an ISO-8601 duration in either form:

Designator form     P[nY][nMo][nW][nD][T[nH][nMi][nS]]
Date-and-time form  PYYYY-MM-DDTHH:MM:SS[.fraction]

Fractional components are supported for the final emitted unit (per openCypher); internally the parser absorbs fractional months/days as fractional seconds added to the appropriate component.

func SubDateTimes

func SubDateTimes(a, b DateTimeValue) DurationValue

SubDateTimes returns a-b as a duration with the same calendar-based decomposition as SubLocalDateTimes, but anchored on the absolute instant (both sides shifted to UTC before the calendar walk). Per openCypher, the duration between two DateTime values is independent of their local zones — what matters is the elapsed time on the global timeline. Without the UTC shift, the wall-clock-anchored diff drifts by the zone offset (e.g. 2014-07-21T21:40+0200 to 2015-07-21T21:40+0100 would report P11M instead of P1Y).

func SubDates

func SubDates(a, b DateValue) DurationValue

SubDates returns the duration from b to a (a - b) using calendar-based decomposition into (months, days). Per openCypher, duration.between(date('1984-10-11'), date('2015-06-24')) yields P30Y8M13D — a calendar-anchored count of whole months between the boundaries, with the leftover days projected onto the closing month.

func SubDurations

func SubDurations(a, b DurationValue) DurationValue

SubDurations returns a-b.

func SubLocalDateTimes

func SubLocalDateTimes(a, b LocalDateTimeValue) DurationValue

SubLocalDateTimes returns a-b as a duration with calendar-based (months, days) plus the wall-clock (hours, minutes, seconds, nanos) remainder. Per openCypher, duration.between of two date-bearing temporals decomposes into the canonical PnYnMnDTnHnMnS form.

func SubLocalTimes

func SubLocalTimes(a, b LocalTimeValue) DurationValue

SubLocalTimes returns a-b as a duration in (Seconds, Nanos).

func SubTimes

func SubTimes(a, b TimeValue) DurationValue

SubTimes returns a-b as a duration in (Seconds, Nanos), normalising both sides to UTC before subtracting. Per openCypher, duration.between(time('14:30'), time('16:30+0100')) yields PT1H — the +01:00 zone shifts the second value's UTC equivalent to 15:30, so the difference is one hour, not two.

func (DurationValue) Equal

func (v DurationValue) Equal(other Value) Value

Equal implements Value with 3VL semantics. Component-wise equality.

func (DurationValue) Hash

func (v DurationValue) Hash() uint64

Hash implements Value.

func (DurationValue) Kind

func (v DurationValue) Kind() Kind

Kind implements Value.

func (DurationValue) String

func (v DurationValue) String() string

String renders ISO-8601 duration: P[nM][nD]T[nS]. Always emits the leading "P" and the "T" separator. Zero components are omitted; the all-zero duration renders as "PT0S".

type EvalError

type EvalError struct {
	Msg string
}

EvalError is returned when Eval encounters a type or semantic error that is not representable as a NULL (e.g. unknown operator, unsupported AST node).

func (*EvalError) Error

func (e *EvalError) Error() string

Error implements the error interface.

type FloatValue

type FloatValue float64

FloatValue is a 64-bit IEEE-754 floating-point Cypher value.

func (FloatValue) Equal

func (v FloatValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue per IEEE-754 equality otherwise (NaN != NaN). Cross-type Int/Float comparison treats 1.0 == 1 as true, per openCypher numeric equality.

func (FloatValue) Hash

func (v FloatValue) Hash() uint64

Hash implements Value.

func (FloatValue) Kind

func (v FloatValue) Kind() Kind

Kind implements Value.

func (FloatValue) String

func (v FloatValue) String() string

String returns the decimal representation of the float.

type FunctionRegistry

type FunctionRegistry interface {
	// Resolve returns the BuiltinFn for name, or (nil, false) when unknown.
	// name is lower-cased by the caller before lookup.
	Resolve(name string) (BuiltinFn, bool)
}

FunctionRegistry resolves built-in and user-defined functions by name. Implementations must be safe for concurrent use (read-only after init).

type IntegerValue

type IntegerValue int64

IntegerValue is a 64-bit signed integer Cypher value.

func (IntegerValue) Equal

func (v IntegerValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue(true) when both sides hold the same numeric value (cross-type Int/Float comparison treats 1 == 1.0 as true, per openCypher numeric equality), BoolValue(false) otherwise.

func (IntegerValue) Hash

func (v IntegerValue) Hash() uint64

Hash implements Value.

func (IntegerValue) Kind

func (v IntegerValue) Kind() Kind

Kind implements Value.

func (IntegerValue) String

func (v IntegerValue) String() string

String returns the decimal representation of the integer.

type Kind

type Kind uint8

Kind identifies the concrete type of a Value.

const (
	// KindDate identifies a calendar date (year/month/day).
	KindDate Kind = iota + 16
	// KindLocalDateTime identifies a naive date-time (no zone).
	KindLocalDateTime
	// KindDateTime identifies a zoned date-time.
	KindDateTime
	// KindLocalTime identifies a naive time-of-day.
	KindLocalTime
	// KindTime identifies a zoned time-of-day.
	KindTime
	// KindDuration identifies an ISO-8601 duration.
	KindDuration
)

Temporal kind tags. These are appended to the Kind enumeration after the existing graph kinds; ordering for Compare is documented in [kindOrder].

const (
	// KindNull is the NULL kind.
	KindNull Kind = iota
	// KindInteger is the 64-bit signed integer kind.
	KindInteger
	// KindFloat is the 64-bit IEEE-754 float kind.
	KindFloat
	// KindString is the UTF-8 string kind.
	KindString
	// KindBool is the boolean kind.
	KindBool
	// KindList is the ordered list kind.
	KindList
	// KindMap is the property map kind.
	KindMap
	// KindNode is the graph node kind.
	KindNode
	// KindRelationship is the graph relationship kind.
	KindRelationship
	// KindPath is the graph path kind.
	KindPath
)

func (Kind) String

func (k Kind) String() string

String returns a human-readable label for the kind.

type ListValue

type ListValue []Value

ListValue is an ordered list of Cypher values.

func (ListValue) Equal

func (v ListValue) Equal(other Value) Value

Equal returns Null if either operand is Null or contains Null. Returns BoolValue(false) if lengths differ. Otherwise returns Null if any element comparison yields Null, else BoolValue(all elements equal).

func (ListValue) Hash

func (v ListValue) Hash() uint64

Hash combines element hashes using a polynomial rolling hash.

func (ListValue) Kind

func (v ListValue) Kind() Kind

Kind implements Value.

func (ListValue) String

func (v ListValue) String() string

String returns the Cypher list literal representation.

type LocalDateTimeValue

type LocalDateTimeValue struct {
	// T carries date and time components. The location is always set to UTC
	// for canonical storage; callers must not interpret it as a real offset.
	T time.Time
}

LocalDateTimeValue is a date + time with no zone. Internally stored as time.Time in UTC; the UTC interpretation is a sentinel, not a real zone.

func AddDurationToLocalDateTime

func AddDurationToLocalDateTime(v LocalDateTimeValue, d DurationValue) LocalDateTimeValue

AddDurationToLocalDateTime adds d to v: months → days → seconds → nanos.

func NewLocalDateTime

func NewLocalDateTime(y, mo, d, h, mi, s, ns int) LocalDateTimeValue

NewLocalDateTime constructs a LocalDateTimeValue from components.

func ParseLocalDateTime

func ParseLocalDateTime(s string) (LocalDateTimeValue, error)

ParseLocalDateTime parses ISO-8601 local date-time: YYYY-MM-DDTHH:MM:SS[.frac] with no zone suffix. Both extended (with separators) and compact forms are accepted; the 'T' separator may be lowercase. A bare date with no time component is accepted as midnight (00:00:00.000000000).

func SubDurationFromLocalDateTime

func SubDurationFromLocalDateTime(v LocalDateTimeValue, d DurationValue) LocalDateTimeValue

SubDurationFromLocalDateTime is the inverse of AddDurationToLocalDateTime.

func (LocalDateTimeValue) Equal

func (v LocalDateTimeValue) Equal(other Value) Value

Equal implements Value with 3VL semantics. Two LocalDateTimeValues are equal iff their components are identical to the nanosecond.

func (LocalDateTimeValue) Hash

func (v LocalDateTimeValue) Hash() uint64

Hash implements Value.

func (LocalDateTimeValue) Kind

func (v LocalDateTimeValue) Kind() Kind

Kind implements Value.

func (LocalDateTimeValue) String

func (v LocalDateTimeValue) String() string

String renders ISO-8601 yyyy-mm-ddThh:mm:ss[.frac] with no zone suffix.

type LocalTimeValue

type LocalTimeValue struct {
	// Nanos is the number of nanoseconds since midnight, in [0, 86_400_000_000_000).
	Nanos int64
}

LocalTimeValue is a time-of-day with nanosecond precision and no zone.

func AddDurationToLocalTime

func AddDurationToLocalTime(v LocalTimeValue, d DurationValue) LocalTimeValue

AddDurationToLocalTime wraps modulo 24h.

func NewLocalTime

func NewLocalTime(h, m, s, ns int) LocalTimeValue

NewLocalTime constructs a LocalTimeValue from clock components.

func ParseLocalTime

func ParseLocalTime(s string) (LocalTimeValue, error)

ParseLocalTime parses ISO-8601 time strings without zone: HH:MM:SS[.frac], HHMMSS[.frac], HH:MM, HHMM, HH.

func SubDurationFromLocalTime

func SubDurationFromLocalTime(v LocalTimeValue, d DurationValue) LocalTimeValue

SubDurationFromLocalTime is the inverse of AddDurationToLocalTime.

func (LocalTimeValue) Equal

func (v LocalTimeValue) Equal(other Value) Value

Equal implements Value with 3VL semantics.

func (LocalTimeValue) Hash

func (v LocalTimeValue) Hash() uint64

Hash implements Value.

func (LocalTimeValue) Kind

func (v LocalTimeValue) Kind() Kind

Kind implements Value.

func (LocalTimeValue) String

func (v LocalTimeValue) String() string

String renders ISO-8601 hh:mm:ss[.frac].

type MapValue

type MapValue map[string]Value

MapValue is a property map from string keys to Cypher values.

func (MapValue) Equal

func (v MapValue) Equal(other Value) Value

Equal returns Null if either operand is Null. Returns BoolValue(false) if key sets differ. Otherwise returns Null if any value comparison yields Null, else BoolValue(all values equal).

func (MapValue) Hash

func (v MapValue) Hash() uint64

Hash combines key and value hashes using XOR so the result is order-independent (map semantics).

func (MapValue) Kind

func (v MapValue) Kind() Kind

Kind implements Value.

func (MapValue) String

func (v MapValue) String() string

String returns the Cypher map literal representation.

type NodeValue

type NodeValue struct {
	ID         uint64
	Labels     []string
	Properties MapValue
	// Deleted reports whether the entity has been removed by an earlier
	// DELETE / DETACH DELETE clause in the same statement. Property and
	// label accessors raise EntityNotFound: DeletedEntityAccess when
	// Deleted is true (openCypher 9 §3.5.8 Return2 [15]/[16]); identity
	// accessors (id, type) and the structural fields (ID, Type) stay
	// readable so `RETURN type(r)` after `DELETE r` still works.
	Deleted bool
}

NodeValue represents a graph node at runtime. ID is the storage-layer node identifier. Labels and Properties are the node's metadata as returned by the persistence layer.

func (NodeValue) Equal

func (v NodeValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue(true) iff both refer to the same node (node identity per openCypher semantics). The peer may be a NodeValue (canonical projected form) or an IntegerValue carrying the raw NodeID (the in-pipeline encoding emitted by NodeScan/Expand); both forms compare on the underlying ID so `n = m` and similar equalities work when one operand has flowed through a projection and the other has not.

func (NodeValue) Hash

func (v NodeValue) Hash() uint64

Hash implements Value; identity is determined by ID.

func (NodeValue) Kind

func (v NodeValue) Kind() Kind

Kind implements Value.

func (NodeValue) String

func (v NodeValue) String() string

String returns a short diagnostic representation of the node.

type PathValue

type PathValue struct {
	Nodes         []NodeValue
	Relationships []RelationshipValue
}

PathValue represents an alternating sequence of nodes and relationships. Nodes has length len(Relationships)+1. An empty path contains exactly one node and no relationships.

func (PathValue) Equal

func (v PathValue) Equal(other Value) Value

Equal returns Null if other is Null. Two paths are equal iff they have the same sequence of node and relationship identities.

func (PathValue) Hash

func (v PathValue) Hash() uint64

Hash combines the hashes of the constituent nodes and relationships.

func (PathValue) Kind

func (v PathValue) Kind() Kind

Kind implements Value.

func (PathValue) String

func (v PathValue) String() string

String returns the openCypher diagnostic representation of the path, wrapped in `<…>` so a path is visibly distinct from a bare node or relationship value. A zero-relationship path of a single node renders as `<(node)>`, matching the TCK convention.

Each relationship is rendered direction-aware against the path's traversal order: when the relationship's storage StartID matches the preceding node, the forward form `-[rel]->` is used; otherwise the reverse form `<-[rel]-` is used. The renderer compares against the rel's StartID rather than re-querying the graph so a relationship projected with explicit direction (e.g. by the named-path fast path) renders consistently.

type PatternEvaluator

type PatternEvaluator interface {
	// EvalPattern evaluates pp as an existential predicate and returns a boolean
	// Value indicating whether the pattern matches at least one path in the graph.
	EvalPattern(ctx context.Context, pp *ast.PathPattern, row RowContext, params map[string]Value) (Value, error)
	// EvalPatternComp evaluates pc as a list-producing pattern
	// comprehension and returns the projected list. The runtime
	// implementation iterates every match of pc.Pattern with the
	// bindings in row as anchors.
	EvalPatternComp(ctx context.Context, pc *ast.PatternComprehension, row RowContext, params map[string]Value, reg FunctionRegistry) (Value, error)
}

PatternEvaluator evaluates ast.PathPattern expressions used as existential predicates inside WHERE clauses (e.g. WHERE (a)-[:T]->(b)). The evaluator receives the current row context so that bound variables are visible and can be used as anchors for the graph traversal.

EvalPattern must return BoolValue(true) when at least one match for the pattern exists in the graph given the bindings in row, BoolValue(false) when no match exists, or Null when the result is undefined. It must honour the supplied context for cancellation and propagate errors unchanged.

EvalPatternComp is the list-producing variant used for ast.PatternComprehension expressions that survive IR hoisting (e.g. when nested inside a ast.ListComprehension's predicate or projection, where lifting the comprehension out of the per-iteration scope would lose the iteration variable binding). It enumerates every match of pc.Pattern given the bindings in row, evaluates the per-match projection (or returns the matched relationship for the projection-less form), and returns the collected ListValue. WHERE predicates declared inside the comprehension are honoured.

type RelationshipValue

type RelationshipValue struct {
	ID         uint64
	StartID    uint64
	EndID      uint64
	Type       string
	Properties MapValue
	// Deleted — see [NodeValue.Deleted].
	Deleted bool
}

RelationshipValue represents a graph relationship at runtime. ID is the storage-layer edge identifier. StartID and EndID are the endpoint node IDs.

func (RelationshipValue) Equal

func (v RelationshipValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue(true) iff both refer to the same relationship (relationship identity per openCypher semantics). Symmetric to NodeValue.Equal: the peer may be a RelationshipValue (canonical projected form) or an IntegerValue carrying the raw edge ID (the in-pipeline encoding emitted by Expand), so `r = s` compares on the underlying ID regardless of which side has flowed through a projection.

func (RelationshipValue) Hash

func (v RelationshipValue) Hash() uint64

Hash implements Value; identity is determined by ID.

func (RelationshipValue) Kind

func (v RelationshipValue) Kind() Kind

Kind implements Value.

func (RelationshipValue) String

func (v RelationshipValue) String() string

String returns a short diagnostic representation of the relationship.

type RowContext

type RowContext map[string]Value

RowContext maps variable names to their current runtime values. It is typically derived from the current operator row plus the schema mapping maintained by the executor.

type StringValue

type StringValue string

StringValue is a UTF-8 string Cypher value.

func (StringValue) Equal

func (v StringValue) Equal(other Value) Value

Equal returns Null if other is Null, BoolValue per string equality otherwise.

func (StringValue) Hash

func (v StringValue) Hash() uint64

Hash implements Value using FNV-1a for zero-alloc performance.

func (StringValue) Kind

func (v StringValue) Kind() Kind

Kind implements Value.

func (StringValue) String

func (v StringValue) String() string

String returns the value enclosed in double quotes.

type SubqueryEvaluator

type SubqueryEvaluator interface {
	// EvalExists evaluates an EXISTS { … } subquery against row and returns
	// BoolValue(true) iff the inner plan emits at least one row.
	EvalExists(ctx context.Context, sub *ast.ExistsSubquery, row RowContext, params map[string]Value) (Value, error)
	// EvalCount evaluates a COUNT { … } subquery against row and returns an
	// IntegerValue equal to the number of rows the inner plan emits.
	EvalCount(ctx context.Context, sub *ast.CountSubquery, row RowContext, params map[string]Value) (Value, error)
}

SubqueryEvaluator drives ast.ExistsSubquery and ast.CountSubquery expressions at evaluation time. The expression evaluator dispatches every subquery occurrence to one of these methods, passing the current outer row so that correlated bindings are visible inside the subquery.

Implementations must:

  • return BoolValue(true) when the inner plan produces ≥1 row, BoolValue(false) otherwise (EvalExists);
  • return IntegerValue equal to the exact row count produced by the inner plan, 0 when empty (EvalCount);
  • honour the context (used for cancellation and deadlines);
  • propagate any error from the inner plan unchanged.

Implementations are expected to compile the subquery's AST once per outer query and reuse the compiled operator across outer rows; per-row state is reset by re-seeding the inner [Argument] leaf via the IR's ArgTag wiring.

type TimeValue

type TimeValue struct {
	// Nanos is the number of nanoseconds since midnight, in [0, 86_400_000_000_000).
	Nanos int64
	// OffsetSec is the zone offset in seconds east of UTC. UTC is 0.
	OffsetSec int32
}

TimeValue is a time-of-day with zone offset (seconds east of UTC).

func AddDurationToTime

func AddDurationToTime(v TimeValue, d DurationValue) TimeValue

AddDurationToTime wraps modulo 24h, preserving zone offset.

func NewTime

func NewTime(h, m, s, ns, offsetSec int) TimeValue

NewTime constructs a TimeValue from clock components and a zone offset in seconds east of UTC.

func ParseTime

func ParseTime(s string) (TimeValue, error)

ParseTime parses ISO-8601 time strings WITH zone: HH:MM:SS[.frac]±HH:MM or HH:MM:SS[.frac]Z. Bare time strings (no zone) are rejected.

func SubDurationFromTime

func SubDurationFromTime(v TimeValue, d DurationValue) TimeValue

SubDurationFromTime is the inverse of AddDurationToTime.

func (TimeValue) Equal

func (v TimeValue) Equal(other Value) Value

Equal implements Value with 3VL semantics. Two TimeValues are equal iff both Nanos and OffsetSec are identical (note: 12:00+00 ≠ 13:00+01:00 even though they refer to the same instant; this matches openCypher).

func (TimeValue) Hash

func (v TimeValue) Hash() uint64

Hash implements Value.

func (TimeValue) Kind

func (v TimeValue) Kind() Kind

Kind implements Value.

func (TimeValue) String

func (v TimeValue) String() string

String renders ISO-8601 hh:mm:ss[.frac] + zone offset.

type Value

type Value interface {
	// Kind returns the kind tag of this value.
	Kind() Kind

	// Equal returns the three-valued equality result: Null if either operand is
	// Null, BoolValue(true/false) otherwise. Callers must never compare Value
	// using Go == ; use Equal and then [IsTruthy].
	Equal(other Value) Value

	// Hash returns a hash suitable for use as a map key. Two values that are
	// equal (per openCypher semantics, i.e., IsTruthy(a.Equal(b))) must have
	// the same hash. NULL has a defined hash (0) but must never be used as a
	// map key in practice.
	Hash() uint64

	// String returns a human-readable representation of the value.
	String() string
}

Value is a typed, immutable Cypher runtime datum. Implementations must be comparable by [Equal] and hashable by [Hash]. All implementations in this package are safe for concurrent reads without external locking.

var Null Value = nullValue{}

Null is the NULL singleton. Comparisons against NULL always return Null.

func Eval

func Eval(expr ast.Expression, row RowContext, params map[string]Value, reg FunctionRegistry) (Value, error)

Eval evaluates expr in the context of row and params. It dispatches on the concrete AST node type and returns the resulting Value. An EvalError is returned for unsupported constructs; all other errors propagate from the function registry.

If reg is nil, function invocations return an EvalError.

Eval does not support subquery expressions (ast.ExistsSubquery, ast.CountSubquery); these return an EvalError. Use EvalWith with a non-nil SubqueryEvaluator to enable subquery evaluation.

Example

ExampleEval evaluates the arithmetic expression `$base + n` where n comes from the row and base from the params map. The result is an IntegerValue.

package main

import (
	"fmt"

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

// noRegistry is a FunctionRegistry that resolves nothing; the examples below
// evaluate operator expressions that need no function lookup.
type noRegistry struct{}

func (noRegistry) Resolve(string) (expr.BuiltinFn, bool) { return nil, false }

func main() {
	// AST for: n + $base
	e := &ast.BinaryOp{
		Operator: "+",
		Left:     &ast.Variable{Name: "n"},
		Right:    &ast.Parameter{Name: "base"},
	}

	row := expr.RowContext{"n": expr.IntegerValue(40)}
	params := map[string]expr.Value{"base": expr.IntegerValue(2)}

	v, err := expr.Eval(e, row, params, noRegistry{})
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("kind:", v.Kind())
	fmt.Println("value:", v) // IntegerValue.String prints the decimal form.
}
Output:
kind: Integer
value: 42
Example (NullPropagation)

ExampleEval_nullPropagation shows openCypher three-valued logic: any comparison involving NULL evaluates to NULL, not false. IsNull reports the outcome.

package main

import (
	"fmt"

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

// noRegistry is a FunctionRegistry that resolves nothing; the examples below
// evaluate operator expressions that need no function lookup.
type noRegistry struct{}

func (noRegistry) Resolve(string) (expr.BuiltinFn, bool) { return nil, false }

func main() {
	// AST for: n > 1, with n bound to NULL.
	e := &ast.BinaryOp{
		Operator: ">",
		Left:     &ast.Variable{Name: "n"},
		Right:    &ast.IntLiteral{Value: 1},
	}

	row := expr.RowContext{"n": expr.Null}

	v, err := expr.Eval(e, row, nil, noRegistry{})
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("is null:", expr.IsNull(v))
}
Output:
is null: true

func EvalWith

func EvalWith(ctx context.Context, expr ast.Expression, row RowContext, params map[string]Value, reg FunctionRegistry, subEval SubqueryEvaluator, patEval PatternEvaluator) (Value, error)

EvalWith evaluates expr just like Eval, but threads a context.Context and optional evaluators through the evaluation. The context is used for cancellation and deadlines when subquery or pattern evaluation is involved. subEval handles ast.ExistsSubquery and ast.CountSubquery occurrences; patEval handles ast.PathPattern existential predicates in WHERE clauses.

When subEval is nil, subquery expressions produce an EvalError. When patEval is nil, pattern predicate expressions produce an EvalError.

EvalWith is safe for concurrent use: each call carries its own context and evaluators on the call stack; there is no shared mutable state.

Jump to

Keyboard shortcuts

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