Documentation
¶
Index ¶
- Variables
- func CollectCorrelatedToOfPredicate(p QueryPredicate, out map[CorrelationIdentifier]struct{}) map[CorrelationIdentifier]struct{}
- func ConstantAgnosticHashCode(p QueryPredicate) uint64
- func ContainsExistentialPredicate(p QueryPredicate) bool
- func CountConjuncts(preds []QueryPredicate) int
- func DependsOnStatementClock(p QueryPredicate) bool
- func GetCorrelatedToOfPredicate(p QueryPredicate) map[CorrelationIdentifier]struct{}
- func IsAtomic(p QueryPredicate) bool
- func IsContradiction(p QueryPredicate) bool
- func IsExistentialPredicate(p QueryPredicate) (values.CorrelationIdentifier, bool)
- func IsLeafQueryPredicate(p QueryPredicate) bool
- func IsNotExistentialPredicate(p QueryPredicate) (values.CorrelationIdentifier, bool)
- func IsTautology(p QueryPredicate) bool
- func PredicateEquals(a, b QueryPredicate) bool
- func PredicateSize(p QueryPredicate) int
- func ReadsConstantPool(p QueryPredicate) bool
- func SemanticEqualsUnderAliasMap(a, b QueryPredicate, aliases values.AliasMap) bool
- func SemanticHashCode(p QueryPredicate) uint64
- func StructuralHash(p QueryPredicate) uint64
- func StructurallyEqual(a, b QueryPredicate) bool
- func WalkPredicate(p QueryPredicate, visit func(QueryPredicate) bool)
- type AndPredicate
- type Comparison
- type ComparisonPredicate
- type ComparisonRange
- func (r *ComparisonRange) GetComparisons() []*Comparison
- func (r *ComparisonRange) GetEqualityComparison() *Comparison
- func (r *ComparisonRange) GetInequalityComparisons() []*Comparison
- func (r *ComparisonRange) GetRangeType() ComparisonRangeType
- func (r *ComparisonRange) IsEmpty() bool
- func (r *ComparisonRange) IsEquality() bool
- func (r *ComparisonRange) IsInequality() bool
- func (r *ComparisonRange) Merge(c *Comparison) MergeResult
- func (r *ComparisonRange) MergeRange(other *ComparisonRange) MergeResult
- type ComparisonRangeType
- type ComparisonType
- type CompatibleTypeEvolutionPredicate
- type ConstantPredicate
- type CorrelationIdentifier
- type DatabaseObjectDependenciesPredicate
- func (*DatabaseObjectDependenciesPredicate) Children() []QueryPredicate
- func (p *DatabaseObjectDependenciesPredicate) Eval(evalCtx any) (TriBool, error)
- func (p *DatabaseObjectDependenciesPredicate) Explain() string
- func (*DatabaseObjectDependenciesPredicate) GetCorrelatedTo() map[CorrelationIdentifier]struct{}
- func (p *DatabaseObjectDependenciesPredicate) UnavailableDependency(avail IndexAvailability) (name string, reason string, ok bool)
- type ExistentialValuePredicate
- func (*ExistentialValuePredicate) Children() []QueryPredicate
- func (*ExistentialValuePredicate) Eval(any) (TriBool, error)
- func (p *ExistentialValuePredicate) Explain() string
- func (p *ExistentialValuePredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
- func (p *ExistentialValuePredicate) GetExistentialAlias() values.CorrelationIdentifier
- type FieldAccessTrieNode
- type IndexAvailability
- type MergeResult
- type NonResidualPredicateError
- type NotPredicate
- type OrPredicate
- type Placeholder
- func (*Placeholder) Children() []QueryPredicate
- func (*Placeholder) Eval(_ any) (TriBool, error)
- func (p *Placeholder) Explain() string
- func (p *Placeholder) GetComparisonRange() *ComparisonRange
- func (p *Placeholder) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
- func (p *Placeholder) GetParameterAlias() values.CorrelationIdentifier
- func (p *Placeholder) GetValue() values.Value
- func (p *Placeholder) IsConstraining() bool
- func (p *Placeholder) Negate() QueryPredicate
- func (p *Placeholder) WithRange(cr *ComparisonRange) *Placeholder
- type PredicateWithValueAndRanges
- func (p *PredicateWithValueAndRanges) Children() []QueryPredicate
- func (p *PredicateWithValueAndRanges) Eval(_ any) (TriBool, error)
- func (p *PredicateWithValueAndRanges) Explain() string
- func (p *PredicateWithValueAndRanges) GetComparisons() []Comparison
- func (p *PredicateWithValueAndRanges) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
- func (p *PredicateWithValueAndRanges) GetRanges() []*RangeConstraints
- func (p *PredicateWithValueAndRanges) GetValue() values.Value
- func (p *PredicateWithValueAndRanges) IsCompileTime() bool
- func (p *PredicateWithValueAndRanges) WithRanges(ranges []*RangeConstraints) *PredicateWithValueAndRanges
- func (p *PredicateWithValueAndRanges) WithValue(v values.Value) *PredicateWithValueAndRanges
- type QueryPredicate
- func EvaluatePredicateComparands(p QueryPredicate) QueryPredicate
- func ExistsValueToQueryPredicate(ev *values.ExistsValue) QueryPredicate
- func FindStructuralPredicate(p QueryPredicate) (QueryPredicate, bool)
- func FlattenConjunction(preds []QueryPredicate) []QueryPredicate
- func FoldComparisonMaybe(lhsValue values.Value, comp Comparison) QueryPredicate
- func PartitionPredicates(predicates []QueryPredicate) []QueryPredicate
- func RebasePredicateChecked(p QueryPredicate, aliases values.AliasMap) (QueryPredicate, error)
- func ReplaceValues(p QueryPredicate, fn func(values.Value) values.Value) QueryPredicate
- func SimplifyPredicateValues(p QueryPredicate) QueryPredicate
- func ToResidualPredicate(p QueryPredicate) (QueryPredicate, error)
- func ToResidualPredicates(preds []QueryPredicate) ([]QueryPredicate, error)
- func TransformEmbeddedValues(p QueryPredicate, transform func(values.Value) values.Value) QueryPredicate
- func TransformEmbeddedValuesChecked(p QueryPredicate, transform func(values.Value) (values.Value, error)) (QueryPredicate, error)
- func TranslateLeafPredicates(p QueryPredicate, m values.TranslationMap) QueryPredicate
- func TranslateLeafPredicatesChecked(p QueryPredicate, m values.TranslationMap) (QueryPredicate, error)
- func WithAtomicity(p QueryPredicate, atomic bool) QueryPredicate
- type RangeConstraints
- func (r *RangeConstraints) AsComparisonRange() (*ComparisonRange, bool)
- func (r *RangeConstraints) Encloses(other *RangeConstraints) bool
- func (r *RangeConstraints) GetComparisons() []Comparison
- func (r *RangeConstraints) GetCompilableComparisons() []Comparison
- func (r *RangeConstraints) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
- func (r *RangeConstraints) GetDeferredRanges() []Comparison
- func (r *RangeConstraints) IsCompileTime() bool
- func (r *RangeConstraints) IsConstraining() bool
- type RangeConstraintsBuilder
- type TemporalCarrierError
- type TriBool
- type TypeMismatchError
- type UsedIndex
- type ValuePredicate
Constants ¶
This section is empty.
Variables ¶
var RelOpComparisonType = map[values.RelOpComparison]ComparisonType{ values.RelOpEquals: ComparisonEquals, values.RelOpNotEquals: ComparisonNotEquals, values.RelOpLessThan: ComparisonLessThan, values.RelOpLessThanOrEquals: ComparisonLessThanOrEq, values.RelOpGreaterThan: ComparisonGreaterThan, values.RelOpGreaterThanOrEquals: ComparisonGreaterThanEq, values.RelOpIsDistinctFrom: ComparisonIsDistinctFrom, values.RelOpNotDistinctFrom: ComparisonNotDistinctFrom, values.RelOpIsNull: ComparisonIsNull, values.RelOpNotNull: ComparisonIsNotNull, }
RelOpComparisonType is the predicate comparison a RelOpValue's comparison becomes (RelOpValue.toQueryPredicate).
Functions ¶
func CollectCorrelatedToOfPredicate ¶
func CollectCorrelatedToOfPredicate(p QueryPredicate, out map[CorrelationIdentifier]struct{}) map[CorrelationIdentifier]struct{}
CollectCorrelatedToOfPredicate unions p's correlations into out, allocating out when nil. Callers folding several predicates can share one result set.
func ConstantAgnosticHashCode ¶
func ConstantAgnosticHashCode(p QueryPredicate) uint64
ConstantAgnosticHashCode is SemanticHashCode with constants hashed by type.
func ContainsExistentialPredicate ¶
func ContainsExistentialPredicate(p QueryPredicate) bool
ContainsExistentialPredicate finds structural existential markers, including their residual QOV IS NOT NULL form, anywhere in the predicate tree.
func CountConjuncts ¶
func CountConjuncts(preds []QueryPredicate) int
CountConjuncts returns the number of independent AND-conjuncts in preds, flattening AndPredicate nodes (recursively, so a nested AND(AND(a,b),c) counts as 3) — the same logical residual predicate SET produces the same count regardless of whether the CONSTRUCTING rule happened to combine conjuncts into one AndPredicate or leave them as separate top-level list entries. Every non-AND predicate (including OR/NOT, treated as one opaque unit — this is a conjunct count, not full CNF expansion) counts as exactly 1. An empty result floors at 1, matching FilterCost's "a zero-predicate filter still pays one selectivity factor" convention.
Exists because NestedLoopJoinCost and PredicatesFilter's own numPreds (both a per-conjunct selectivity-compounding cost, cost_formulas.go) otherwise disagree on a residual that reaches one path as N separate QueryPredicate list entries and the other as one AndPredicate combining the same N conditions — a representation artifact, not a difference in the true selectivity, so the SAME logical join was costed two different ways depending on which physical shape happened to receive which packaging.
func DependsOnStatementClock ¶
func DependsOnStatementClock(p QueryPredicate) bool
func GetCorrelatedToOfPredicate ¶
func GetCorrelatedToOfPredicate(p QueryPredicate) map[CorrelationIdentifier]struct{}
GetCorrelatedToOfPredicate returns transitive correlations as a fresh map. Nil input returns nil; an uncorrelated predicate returns a non-nil empty map.
func IsAtomic ¶
func IsAtomic(p QueryPredicate) bool
IsAtomic reports whether boolean normalization must treat this subtree as a leaf.
func IsContradiction ¶
func IsContradiction(p QueryPredicate) bool
IsContradiction reports whether the predicate always evaluates to FALSE.
func IsExistentialPredicate ¶
func IsExistentialPredicate(p QueryPredicate) (values.CorrelationIdentifier, bool)
IsExistentialPredicate reports whether p is the existential semi-join shape — an ExistentialValuePredicate (a QuantifiedObjectValue operand with a NOT_NULL comparison) — and if so returns the existential alias. This is the single detection point all EXISTS call sites use, instead of type-switching on a dedicated leaf type (RFC-141: one mechanism).
It also recognises a bare ComparisonPredicate with the same shape (QOV operand + ComparisonIsNotNull), which is what ExistentialValuePredicate lowers to as a residual predicate (Java's toResidualPredicate).
func IsLeafQueryPredicate ¶
func IsLeafQueryPredicate(p QueryPredicate) bool
IsLeafQueryPredicate reports whether `p` is a leaf in the predicate tree (no children). Mirrors Java's `com.apple.foundationdb.record.query.plan.cascades.predicates. LeafQueryPredicate` marker interface — Go expresses this via a runtime function on the existing Children() method instead of a per-type marker mixin (Go-idiomatic).
Use case: a rule that matches only leaf predicates checks IsLeafQueryPredicate(p) before recursing into Children(); avoids tight coupling to specific concrete types (ConstantPredicate / ValuePredicate / ComparisonPredicate / ExistentialValuePredicate / etc.).
func IsNotExistentialPredicate ¶
func IsNotExistentialPredicate(p QueryPredicate) (values.CorrelationIdentifier, bool)
IsNotExistentialPredicate reports whether p is NotPredicate wrapping an existential predicate (the NOT EXISTS shape), returning the alias.
func IsTautology ¶
func IsTautology(p QueryPredicate) bool
IsTautology reports whether the predicate always evaluates to TRUE. Only ConstantPredicate(TRUE) is a tautology; all other predicates return false. Mirrors Java's QueryPredicate.isTautology().
func PredicateEquals ¶
func PredicateEquals(a, b QueryPredicate) bool
PredicateEquals reports structural equality between two QueryPredicates. Two predicates are equal when their concrete Go types match AND their children + carried data match recursively. Constants compare by TriBool identity; ComparisonPredicate compares by operand Name + Comparison (Type + Operand literal); ValuePredicate compares by wrapped Value Name.
Used by the normalization rules (the absorption rules in rule_simplify.go, NormalizePredicatesRule); the equality helper belongs with the predicate types themselves so rule authors don't roll their own.
func PredicateSize ¶
func PredicateSize(p QueryPredicate) int
PredicateSize returns the total node count in p (p + all descendants). Rule authors use this to gate expensive transformations (e.g. De Morgan expansion that would double the size). Constant-time-per-node; cycle-free by construction.
func ReadsConstantPool ¶
func ReadsConstantPool(p QueryPredicate) bool
DependsOnStatementClock reports whether any Value tree embedded in the predicate contains a CURRENT_TIMESTAMP-family function (see values.DependsOnStatementClock). It probes through the SAME spine the value-rewrite families walk (TransformEmbeddedValues), so a predicate shape that carries values cannot be visible to rewrites yet invisible to the statement-clock need check. The probe transform returns every value unchanged, so the pointer-stable spine rebuilds nothing. ReadsConstantPool reports whether p embeds a statement constant reference.
func SemanticEqualsUnderAliasMap ¶
func SemanticEqualsUnderAliasMap(a, b QueryPredicate, aliases values.AliasMap) bool
SemanticEqualsUnderAliasMap is the ALIAS-AWARE, bool counterpart of PredicateEquals: predicates differing only in the quantifier alias their Values reference are equal when those aliases correspond in `aliases`. Operand/child Values compare via values.SemanticEqualsUnderAliasMap.
Lives in the predicates package (RFC-040 040.1b) so expressions' relational EqualsWithoutChildren (040.2) can call it without an import cycle. Consistent with predicates.SemanticHashCode (equal-under-aliases ⟹ equal hash).
func SemanticHashCode ¶
func SemanticHashCode(p QueryPredicate) uint64
SemanticHashCode returns an ALIAS-INVARIANT structural hash of a QueryPredicate, consistent with alias-aware predicate equality (SemanticEqualsUnderAliasMap). Value-bearing predicates fold their Values via the alias-invariant values.SemanticHashCode; ExistentialValuePredicate's operand alias is EXCLUDED; compound predicates recurse via Children() (NOT alias-bearing Explain() text).
Lives in the predicates package (RFC-040 040.1b relocation) so expressions (relational HashCodeWithoutChildren, 040.2) and cascades (memoEqual) can use it without an import cycle.
func StructuralHash ¶
func StructuralHash(p QueryPredicate) uint64
StructuralHash is the hash analog of StructurallyEqual: two predicates that are StructurallyEqual produce the same hash (the equal⟹same-hash invariant the memo relies on). It mirrors StructurallyEqual's comparison exactly — the same discriminators, values.SemanticHashCode for operand Values (itself the hash analog of values.ValuesStructurallyEqual), recursion for And/Or/Not, and the Explain() fallback StructurallyEqual uses in its own default arm.
KEEP IN SYNC with StructurallyEqual (structural_equal.go): any new case there needs the matching case here, or equal predicates could hash differently.
func StructurallyEqual ¶
func StructurallyEqual(a, b QueryPredicate) bool
StructurallyEqual reports whether two predicates are structurally equal: same concrete type, same non-child attributes, and recursively equal children. Mirrors Java's QueryPredicate.semanticEquals for the same-scope case.
func WalkPredicate ¶
func WalkPredicate(p QueryPredicate, visit func(QueryPredicate) bool)
WalkPredicate applies visit to every node in p's subtree, pre-order. If visit returns false, descent into that node's children is skipped (but siblings + ancestors continue). Rule authors use this for tree-wide searches (e.g. "does any descendant reference the discarded correlation ID?").
Safe on nil: returns immediately. Safe on cyclic trees: predicate construction is non-cyclic by contract, so cycle detection is unnecessary.
Types ¶
type AndPredicate ¶
type AndPredicate struct {
SubPredicates []QueryPredicate
// contains filtered or unexported fields
}
AndPredicate is the Kleene AND of children. Empty children yields TRUE (identity). A single FALSE child short-circuits to FALSE. An UNKNOWN + no-FALSE yields UNKNOWN.
func (*AndPredicate) Children ¶
func (p *AndPredicate) Children() []QueryPredicate
func (*AndPredicate) Explain ¶
func (p *AndPredicate) Explain() string
func (*AndPredicate) GetCorrelatedTo ¶
func (p *AndPredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the union of all children's correlations.
type Comparison ¶
type Comparison struct {
Type ComparisonType
Operand values.Value
// ParameterName is set for parameter-bound comparisons (Java's
// ParameterComparison). Non-empty means the RHS is resolved at
// runtime from EvaluationContext.getBinding(ParameterName).
ParameterName string
// TextTokenizerName and TextAnalyzerName are set for text-search
// comparisons (Java's TextComparison). Empty = default tokenizer.
TextTokenizerName string
TextAnalyzerName string
// TextMaxDistance is set for TEXT_CONTAINS_ALL_WITHIN comparisons
// (Java's TextWithMaxDistanceComparison).
TextMaxDistance int
// TextStrictPrefix is set for TEXT_CONTAINS_ALL_PREFIXES comparisons
// (Java's TextContainsAllPrefixesComparison).
TextStrictPrefix bool
// --- DistanceRank fields (Java's DistanceRankValueComparison) ---
// Set only for ComparisonDistanceRank* types — the vector K-NN
// "top-K by distance" comparison produced from
// ROW_NUMBER() OVER (... ORDER BY <distance>(field, q)) {<,<=,=} K.
// Operand carries the K (top-K) comparand; QueryVector is the search
// vector; EfSearch / IsReturningVectors are the HNSW runtime knobs
// threaded from the ROW_NUMBER() OPTIONS clause (nil = index default).
QueryVector values.Value
EfSearch *int
IsReturningVectors *bool
}
Comparison pairs a ComparisonType with a right-hand side `Value`. The LHS lives on the parent ComparisonPredicate; each Comparison carries its own (Type, RHS-Value) pair. Unary comparisons (IS [NOT] NULL) leave Operand nil — Eval ignores it.
The RHS is a Value (not a raw literal) so non-constant RHS shapes — `a = b`, `a < b + 1`, `a = CAST(col AS INT)` — compose uniformly with the LHS. Constant-RHS callers wrap via NewLiteralComparison / LiteralValue. IN-list RHS is carried as a ConstantValue whose Value is a `[]any` of evaluated literals.
A LIKE's Operand is its values.PatternForLikeValue, which carries the pattern and the escape (Java's ValueComparison(LIKE, patternValue)).
func NewDistanceRankComparison ¶
func NewDistanceRankComparison(typ ComparisonType, queryVector, comparand values.Value, efSearch *int, isReturningVectors *bool) (Comparison, bool)
NewDistanceRankComparison builds the vector K-NN distance-rank comparison (Java's Comparisons.DistanceRankValueComparison). comparand is the K (top-K) value and queryVector is the search vector.
Returns ok=false when typ is not a *scannable* distance-rank type. Java's DistanceRankValueComparison constructor asserts `type == DISTANCE_RANK_LESS_THAN || type == DISTANCE_RANK_LESS_THAN_OR_EQUAL` (Comparisons.java) — DISTANCE_RANK_EQUALS is mapped by RowNumberValue.transformComparisonMaybe but then REJECTED at construction, so `ROW_NUMBER() = K` is not expressible as a vector scan. We mirror that here (no panic): the caller treats ok=false as "not lowerable", leaving the row-number comparison unmatched so the query fails to plan, exactly as Java's assertion failure aborts planning.
func NewLiteralComparison ¶
func NewLiteralComparison(typ ComparisonType, lit any) Comparison
NewLiteralComparison is the common-case constructor for a binary Comparison whose RHS is a plan-time literal. Wraps lit in the appropriate Value subtype (NullValue for nil, BooleanValue for bool, ConstantValue otherwise). For unary types callers should set Operand to nil directly: `Comparison{Type: ComparisonIsNull}`. A LIKE comparand is always a PatternForLikeValue, so a LIKE literal is wrapped as a pattern with no escape.
func (Comparison) Eval ¶
func (c Comparison) Eval(left any) (TriBool, error)
Eval compares left against c's (plan-time-evaluated) RHS per c's ComparisonType. The RHS is produced by c.Operand.Evaluate(nil) — i.e. RHS evaluation without a row context. Constant-RHS callers (the common case, and the only shape that can fold at plan time) get their literal back. Non-constant RHS — a FieldValue or an ArithmeticValue over row columns — evaluates to nil here and degrades to UNKNOWN, which is the right answer when no row is in scope. For row-aware evaluation use ComparisonPredicate.Eval, which evaluates both sides against the given eval context.
NULL (nil) on either side returns UNKNOWN per SQL 3VL for binary comparators; unary (IS [NOT] NULL) and null-safe (IS [NOT] DISTINCT FROM) types resolve even on NULL. Numeric operands promote via cmpAny so mixed-width int/float pairs don't degrade to UNKNOWN.
func (Comparison) EvalAgainst ¶
func (c Comparison) EvalAgainst(left, right any) (TriBool, error)
EvalAgainst is the pure dispatch: given already-evaluated LHS and RHS Go-natives, return the Kleene truth value. ComparisonPredicate evaluates both sides against the row's eval context and calls EvalAgainst — separating eval from dispatch is what lets a non-constant RHS (`a = b + 1`) work row-by-row.
func (Comparison) GetCorrelatedTo ¶
func (c Comparison) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the set of correlation identifiers referenced by every Value this comparison carries: its RHS operand and, for distance-rank comparisons, its query vector. Used by ordering-aware rules to match comparison bindings to explode aliases.
type ComparisonPredicate ¶
type ComparisonPredicate struct {
Operand values.Value
Comparison Comparison
}
ComparisonPredicate applies a Comparison to an operand `Value`. The operand is evaluated against a row (the eval context) via Value.Evaluate to produce the left-hand side; the comparison's literal is the right-hand side. Returns UNKNOWN when either side is NULL (SQL 3VL).
func NewComparisonPredicate ¶
func NewComparisonPredicate(operand values.Value, cmp Comparison) *ComparisonPredicate
NewComparisonPredicate builds a ComparisonPredicate.
func TransformRowNumberDistanceRankMaybe ¶
func TransformRowNumberDistanceRankMaybe(rn *values.RowNumberValue, cmpType ComparisonType, comparand values.Value) (*ComparisonPredicate, bool)
TransformRowNumberDistanceRankMaybe ports Java RowNumberValue.transformComparisonMaybe.
A comparison of the shape
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY <distance>(field, queryVec)) {<,<=,=} K
is rewritten into a ComparisonPredicate (Java's ValuePredicate) whose LHS is the distance-specialized row-number value (Euclidean / EuclideanSquare / Cosine / DotProduct) and whose RHS is a DistanceRank comparison capturing the query vector + K (+ the HNSW ef_search / return-vectors knobs). This is the shape the vector index match candidate recognizes and lowers to an HNSW K-NN scan.
Returns (nil, false) when the pattern doesn't match — the ROW_NUMBER argument is not a single distance function, or the comparison is not one of =, <, <= — in which case the caller keeps the original comparison (Java returns Optional.empty()).
Layering note: Java places this method on RowNumberValue itself; in Go the `values` package cannot import `predicates` (predicates depends on values), so the transform lives here as a function over a *values.RowNumberValue.
func (*ComparisonPredicate) Children ¶
func (*ComparisonPredicate) Children() []QueryPredicate
func (*ComparisonPredicate) Explain ¶
func (p *ComparisonPredicate) Explain() string
func (*ComparisonPredicate) GetCorrelatedTo ¶
func (p *ComparisonPredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the union of correlations from the LHS operand Value and everything the RHS Comparison carries.
The comparison's collector includes its query vector as well as its operand; reading only Operand would silently drop DistanceRank correlations.
type ComparisonRange ¶
type ComparisonRange struct {
// contains filtered or unexported fields
}
ComparisonRange represents a contiguous range of values for a single column. Mirrors Java's `com.apple.foundationdb.record.query.plan.cascades.ComparisonRange`.
A range is one of three types:
- Empty: full universe (any value matches).
- Equality: a single equals comparison (col = X).
- Inequality: a set of one or more inequality comparisons (col > X, col < Y, etc.) defining a contiguous range.
Used by index-pushdown rules: when matching predicates against a candidate index, each indexed column gets a ComparisonRange derived from the predicate set. The planner then converts the list of per-column ranges into an index scan key range.
Range type discipline (Java's ComparisonRange.merge, arm for arm):
- A NONE-type comparison (NOT_EQUALS, IN, LIKE, TEXT_*, …) never enters a range; it comes back as a residual and the range is untouched.
- Adding any scan-range comparison to an Empty range produces a non-empty range of the corresponding type.
- Adding an equality to an Equality range is a no-op when the two are the same comparison, and leaves the incoming one as a residual when they differ (the planner scans the first and re-checks the second; a contradiction reads zero rows).
- Adding an inequality to an Equality range leaves it as a residual.
- Adding an inequality to an Inequality range appends it, unless it is already present.
- Adding an equality to an Inequality range makes the equality the range and every accumulated inequality a residual.
The merge is TOTAL: it never fails. MergeResult carries the range plus the residual comparisons, and a caller that cannot carry residuals reads len(Residuals) > 0 as its rejection.
func EmptyComparisonRange ¶
func EmptyComparisonRange() *ComparisonRange
EmptyComparisonRange returns the universe-range singleton. Each call returns a fresh struct so callers can safely mutate via Merge without aliasing.
func (*ComparisonRange) GetComparisons ¶
func (r *ComparisonRange) GetComparisons() []*Comparison
GetComparisons returns every Comparison this range carries, whichever shape it has: the single equality, or all the inequalities. It returns an empty slice for an empty or nil range. The returned slice is read-only. Callers that need to inspect the range as a whole should use this rather than branching on the range type and risking one of the shapes going unhandled.
func (*ComparisonRange) GetEqualityComparison ¶
func (r *ComparisonRange) GetEqualityComparison() *Comparison
GetEqualityComparison returns the single equality comparison. Panics if the range isn't an equality range — callers should guard with IsEquality first.
func (*ComparisonRange) GetInequalityComparisons ¶
func (r *ComparisonRange) GetInequalityComparisons() []*Comparison
GetInequalityComparisons returns the inequality comparison list. Panics if the range isn't an inequality range — callers should guard with IsInequality first. Returns a read-only slice.
func (*ComparisonRange) GetRangeType ¶
func (r *ComparisonRange) GetRangeType() ComparisonRangeType
GetRangeType returns the discriminator.
func (*ComparisonRange) IsEmpty ¶
func (r *ComparisonRange) IsEmpty() bool
IsEmpty reports whether the range is the universe.
func (*ComparisonRange) IsEquality ¶
func (r *ComparisonRange) IsEquality() bool
IsEquality reports whether the range is a single = comparison.
func (*ComparisonRange) IsInequality ¶
func (r *ComparisonRange) IsInequality() bool
IsInequality reports whether the range is a set of inequalities.
func (*ComparisonRange) Merge ¶
func (r *ComparisonRange) Merge(c *Comparison) MergeResult
Merge adds a comparison to the range. Total: the outcome is always a range plus the residual comparisons that did not fit — see the type comment for the arm table (Java's ComparisonRange.merge(Comparison)).
func (*ComparisonRange) MergeRange ¶
func (r *ComparisonRange) MergeRange(other *ComparisonRange) MergeResult
MergeRange merges every comparison another range carries into this one, accumulating the residuals — Java's ComparisonRange.merge(ComparisonRange).
type ComparisonRangeType ¶
type ComparisonRangeType int
ComparisonRangeType discriminates the three range shapes.
const ( // ComparisonRangeEmpty is the universe range — any value matches. ComparisonRangeEmpty ComparisonRangeType = iota // ComparisonRangeEquality is a single = comparison. ComparisonRangeEquality // ComparisonRangeInequality is a set of inequalities. ComparisonRangeInequality )
type ComparisonType ¶
type ComparisonType int
ComparisonType is the operator carried by a Comparison. Enum values match Java's `com.apple.foundationdb.record.query.expressions.Comparisons.Type` ordering so serialised plans round-trip (once we have plan serialisation).
const ( ComparisonEquals ComparisonType = iota // = ComparisonNotEquals // !=, <> ComparisonLessThan // < ComparisonLessThanOrEq // <= ComparisonGreaterThan // > ComparisonGreaterThanEq // >= ComparisonIsNull // IS NULL (unary, LHS-only) ComparisonIsNotNull // IS NOT NULL (unary, LHS-only) ComparisonStartsWith // STARTS_WITH (string LHS, string RHS prefix) ComparisonIn // IN (LHS any, RHS is a []any membership list) ComparisonIsDistinctFrom // IS DISTINCT FROM (null-safe !=) ComparisonNotDistinctFrom // IS NOT DISTINCT FROM (null-safe =) ComparisonLike // LIKE (string LHS, SQL pattern RHS: % / _) ComparisonTextContainsAll // TEXT_CONTAINS_ALL (full-text: all terms must match) ComparisonTextContainsAllWithin // TEXT_CONTAINS_ALL_WITHIN (full-text: all terms within distance) ComparisonTextContainsAny // TEXT_CONTAINS_ANY (full-text: any term matches) ComparisonTextContainsPhrase // TEXT_CONTAINS_PHRASE (full-text: exact phrase match) ComparisonTextContainsPrefix // TEXT_CONTAINS_PREFIX (full-text: prefix of any term) ComparisonTextContainsAllPrefixes // TEXT_CONTAINS_ALL_PREFIXES (full-text: all prefixes match) ComparisonTextContainsAnyPrefix // TEXT_CONTAINS_ANY_PREFIX (full-text: any prefix matches) ComparisonSort // SORT (ordering comparison, not a filter) ComparisonDistanceRankEquals // DISTANCE_RANK_EQUALS (vector distance rank equality) ComparisonDistanceRankLessThan // DISTANCE_RANK_LESS_THAN (vector distance rank bound) ComparisonDistanceRankLessThanOrEq // DISTANCE_RANK_LESS_THAN_OR_EQUAL (vector distance rank bound) )
func (ComparisonType) Commute ¶
func (c ComparisonType) Commute() (ComparisonType, bool)
Commute returns the operator that holds when the two operands are swapped: `a OP b` is equivalent to `b Commute(OP) a`. Equality, not-equals and the null-safe IS [NOT] DISTINCT FROM are symmetric (unchanged); the binary inequalities flip direction, as Java's RelOpValue.swapBinaryComparisonOperator (RelOpValue.java:297-312). Unary operators (IS NULL / IS NOT NULL) and non-commutable operators (IN, STARTS_WITH, LIKE) return (c, false). Used by index/PK matching, which is commutative: a join predicate `outer.fk = inner.pk` constrains inner.pk exactly as `inner.pk = outer.fk` does.
func (ComparisonType) IsEquality ¶
func (c ComparisonType) IsEquality() bool
IsEquality reports whether the comparison semantically tests for (null-safe or null-aware) equality. Mirrors Java's `Comparisons.Type.isEquality()` — useful for index-pushdown decisions (equality predicates can use point-lookups; inequality needs ranges).
IN is deliberately NOT an equality, matching Java's `IN,` — declared with the no-arg constructor, which chains to `this(false)`. It reads like one, and that is the trap: `x IN (1,2,3)` is a DISJUNCTION of equalities, so a caller acting on a true here would bind a single point-lookup key for a predicate that needs three. Java agrees twice over — `ScanComparisons.getComparisonType(IN)` falls to the `default: NONE` arm, so IN is not a scan bound at all.
func (ComparisonType) IsUnary ¶
func (c ComparisonType) IsUnary() bool
IsUnary reports whether the comparison takes no RHS operand (IS NULL / IS NOT NULL). Callers use this to skip Operand-based folding / plumbing for unary predicates.
func (ComparisonType) Negate ¶
func (c ComparisonType) Negate() (ComparisonType, bool)
Negate returns the comparison type whose truth table is the logical negation of this one, plus a flag indicating whether a negation is known. Used by the NOT-over-Comparison rewrite rule when pushing a NOT down past a leaf comparison.
It is Java's Comparisons.invertComparisonType (Comparisons.java:705-723) and nothing more, which means the DECLINES are the interesting half and they are enumerated rather than characterised:
EQUALS -> NOT_EQUALS inverted LESS_THAN -> GREATER_THAN_OR_EQUALS LESS_THAN_OR_EQUALS -> GREATER_THAN GREATER_THAN -> LESS_THAN_OR_EQUALS GREATER_THAN_OR_EQUALS -> LESS_THAN
Everything else declines, and four of those declines are worth naming because a negation plainly EXISTS for them and is still not returned:
- IS NULL / IS NOT NULL. Java's first line is `if (type.isUnary()) return null;`, so the unary null tests are refused before the switch is reached — even though each is the other's exact negation.
- NOT_EQUALS. EQUALS inverts to it and it does not invert back; Java's switch simply has no NOT_EQUALS arm.
- IS DISTINCT FROM / IS NOT DISTINCT FROM, likewise absent from the switch.
These are not oversights to be closed here. This function is a 1:1 port and its result feeds a rewrite that changes what the planner's downstream rules see; widening it beyond Java would make Go's canonical predicate shape differ from Java's for the same query.
func (ComparisonType) Symbol ¶
func (c ComparisonType) Symbol() string
Symbol returns the SQL-text form of the operator.
type CompatibleTypeEvolutionPredicate ¶
type CompatibleTypeEvolutionPredicate struct {
// RecordTypeNameFieldAccessMap maps record type names to their
// field access trie roots. Each trie encodes which fields of
// that record type are accessed by the plan.
RecordTypeNameFieldAccessMap map[string]*FieldAccessTrieNode
}
CompatibleTypeEvolutionPredicate is a leaf predicate used by the plan cache to verify that a cached plan is still valid under the current schema. It carries a list of (recordTypeName, fieldAccessTrieNode) pairs describing which record type fields the plan accesses.
Ports Java's com.apple.foundationdb.record.query.plan.cascades.predicates.CompatibleTypeEvolutionPredicate
At eval time in Java, this checks that the current schema's record types are compatible with the cached plan's field access patterns. In Go, the plan cache is not yet ported, so Eval returns TriTrue unconditionally. The type exists for structural conformance: it can be round-tripped through serialization and participates in predicate equality.
func NewCompatibleTypeEvolutionPredicate ¶
func NewCompatibleTypeEvolutionPredicate(m map[string]*FieldAccessTrieNode) *CompatibleTypeEvolutionPredicate
NewCompatibleTypeEvolutionPredicate constructs the predicate from the given record type -> field access trie mapping.
func (*CompatibleTypeEvolutionPredicate) Children ¶
func (*CompatibleTypeEvolutionPredicate) Children() []QueryPredicate
Children returns nil -- this is a leaf predicate.
func (*CompatibleTypeEvolutionPredicate) Eval ¶
func (*CompatibleTypeEvolutionPredicate) Eval(_ any) (TriBool, error)
Eval returns TriTrue. Plan-cache schema validation is not yet ported; this predicate exists for structural conformance.
func (*CompatibleTypeEvolutionPredicate) Explain ¶
func (p *CompatibleTypeEvolutionPredicate) Explain() string
Explain renders the predicate in a human-readable form matching Java's explain output: compatibleTypeEvolution(<record types>).
func (*CompatibleTypeEvolutionPredicate) GetCorrelatedTo ¶
func (*CompatibleTypeEvolutionPredicate) GetCorrelatedTo() map[CorrelationIdentifier]struct{}
GetCorrelatedTo returns the empty set — type evolution predicates reference no quantifier aliases.
type ConstantPredicate ¶
type ConstantPredicate struct {
Value TriBool
}
ConstantPredicate is a literal truth value (true / false / UNKNOWN). Useful for simplification rules that reduce a subtree to a constant.
func NewConstantPredicate ¶
func NewConstantPredicate(v TriBool) *ConstantPredicate
NewConstantPredicate wraps a TriBool as a ConstantPredicate.
func (*ConstantPredicate) Children ¶
func (*ConstantPredicate) Children() []QueryPredicate
func (*ConstantPredicate) Explain ¶
func (p *ConstantPredicate) Explain() string
func (*ConstantPredicate) GetCorrelatedTo ¶
func (*ConstantPredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the empty set — constants reference no quantifier aliases.
type CorrelationIdentifier ¶
type CorrelationIdentifier = values.CorrelationIdentifier
CorrelationIdentifier is re-exported as a type alias so package consumers don't need to import values just for the map key type.
type DatabaseObjectDependenciesPredicate ¶
type DatabaseObjectDependenciesPredicate struct {
// UsedIndexes is the set of indexes this plan depends on,
// each carrying its name and the lastModifiedVersion at plan
// creation time.
UsedIndexes []UsedIndex
}
DatabaseObjectDependenciesPredicate is a leaf predicate carrying the indexes a plan depends on. It answers one question: may this plan still be executed against the store in front of it?
Ports Java's com.apple.foundationdb.record.query.plan.cascades.predicates.DatabaseObjectDependenciesPredicate. Java attaches it to every planned query as the CONTINUATION plan constraint (QueryPlan.java:667,726-735) and re-evaluates it on every execution, so a resumed page is gated too, not only a first execution.
A dependency is any index whose availability the plan's CORRECTNESS rests on: the indexes it scans, and any index whose metadata property licensed a transformation without being scanned. The second kind is why this cannot be derived from the plan tree alone at evaluation time.
func NewDatabaseObjectDependenciesPredicate ¶
func NewDatabaseObjectDependenciesPredicate(indexes []UsedIndex) *DatabaseObjectDependenciesPredicate
NewDatabaseObjectDependenciesPredicate constructs the predicate from the given set of used indexes.
func (*DatabaseObjectDependenciesPredicate) Children ¶
func (*DatabaseObjectDependenciesPredicate) Children() []QueryPredicate
Children returns nil -- this is a leaf predicate.
func (*DatabaseObjectDependenciesPredicate) Eval ¶
func (p *DatabaseObjectDependenciesPredicate) Eval(evalCtx any) (TriBool, error)
Eval reports whether this plan can still be executed against the store described by evalCtx. Port of Java's eval (DatabaseObjectDependenciesPredicate.java:87-105): every used index must still exist, carry the same lastModifiedVersion, and be readable.
evalCtx MUST implement IndexAvailability. Java takes a non-null store and dereferences it (`Objects.requireNonNull(store)`), so a context that cannot answer is a programming error, not a case to be lenient about: returning TriTrue there would silently pass every dependency check ever made through the wrong call site. An asserted bridge, never a quiet fallback.
A predicate with no dependencies is vacuously TriTrue and needs no context — that is a real absence of dependencies, not an inability to check them.
func (*DatabaseObjectDependenciesPredicate) Explain ¶
func (p *DatabaseObjectDependenciesPredicate) Explain() string
Explain renders the predicate in a human-readable form matching Java's explain output: databaseObjectDependencies(<index names>).
func (*DatabaseObjectDependenciesPredicate) GetCorrelatedTo ¶
func (*DatabaseObjectDependenciesPredicate) GetCorrelatedTo() map[CorrelationIdentifier]struct{}
GetCorrelatedTo returns the empty set — database object dependency predicates reference no quantifier aliases.
func (*DatabaseObjectDependenciesPredicate) UnavailableDependency ¶
func (p *DatabaseObjectDependenciesPredicate) UnavailableDependency( avail IndexAvailability, ) (name string, reason string, ok bool)
UnavailableDependency returns the first used index that fails against avail, and why — the diagnostic Eval's TriFalse deliberately does not carry, since a predicate's job is a truth value. ok=false when every dependency holds.
type ExistentialValuePredicate ¶
type ExistentialValuePredicate struct {
// Value is the operand — always a QuantifiedObjectValue over the
// existential quantifier. Kept as values.Value to mirror Java's
// ValuePredicate.getValue() and because helpers expect the interface.
Value values.Value
// Comparison is always ComparisonIsNotNull (the NullComparison(NOT_NULL)).
Comparison Comparison
}
ExistentialValuePredicate is the QueryPredicate-layer SQL EXISTS, ported from Java 4.12's `com.apple.foundationdb.record.query.plan.cascades.predicates. ExistentialValuePredicate`. It is "the existential quantifier's object is non-null ⇒ the subplan yielded ≥1 row".
In Java it `extends ValuePredicate(value, comparison)` where value is a QuantifiedObjectValue and comparison is NullComparison(NOT_NULL). Go's ValuePredicate is a bare boolean-Value wrapper (no comparison), so the Java (value, comparison) pair maps to the same shape Go's ComparisonPredicate uses: an operand Value + a Comparison. This type carries exactly that, constrained to a QuantifiedObjectValue operand and a ComparisonIsNotNull comparison.
EXISTS (SELECT ... FROM t WHERE ...)
↔ ExistentialValuePredicate{Value: QOV{αsubq}, NOT_NULL}
This is the SINGLE EXISTS predicate representation (RFC-141): it replaces the deleted leaf-alias ExistsPredicate. A NOT-EXISTS is NotPredicate(ExistentialValuePredicate).
Eval is a per-row UNKNOWN at this layer — actual EXISTS evaluation requires running the subplan, which the planner's semi-join rules (ImplementNestedLoopJoinRule) handle structurally. The QOV operand would eval to the bound existential row only inside the FlatMap/ semi-join cursor, not in the generic per-row predicate eval.
func MustNewExistentialValuePredicate ¶
func MustNewExistentialValuePredicate(value values.Value, comparison Comparison) *ExistentialValuePredicate
MustNewExistentialValuePredicate constructs the predicate. The value MUST be a QuantifiedObjectValue; the `Must` prefix is the documented panic contract (Go's regexp.MustCompile convention, mapping to Java's Verify.verify(value instanceof QuantifiedObjectValue)) — a non-QOV operand is a programming error, not a runtime condition. Every call site holds a QOV by construction (a rebased / mapped / decorrelated QOV stays a QOV, and ExistsValueToQueryPredicate passes the ExistsValue's QOV child), so the precondition is a caller-guaranteed structural invariant, not input validation — which is why this asserts rather than returns an error.
func NewExistentialAlias ¶
func NewExistentialAlias( alias values.CorrelationIdentifier, flowed values.Type, ) (*ExistentialValuePredicate, error)
NewExistentialAlias is the convenience constructor over an existential alias and its exact flowed type: it wraps them in a QuantifiedObjectValue with a NOT_NULL comparison. Invalid aliases or unresolved/malformed types are returned to the caller; this boundary never fabricates an untyped QOV.
func (*ExistentialValuePredicate) Children ¶
func (*ExistentialValuePredicate) Children() []QueryPredicate
Children returns the empty slice — leaf in the predicate tree (the QuantifiedObjectValue operand is a carried Value, not a child predicate).
func (*ExistentialValuePredicate) Eval ¶
func (*ExistentialValuePredicate) Eval(any) (TriBool, error)
Eval returns TriUnknown — EXISTS isn't evaluated at the per-row predicate level; the planner's semi-join rules do the row-level test.
func (*ExistentialValuePredicate) Explain ¶
func (p *ExistentialValuePredicate) Explain() string
Explain renders the SQL-ish form.
func (*ExistentialValuePredicate) GetCorrelatedTo ¶
func (p *ExistentialValuePredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the correlations of the operand Value — the existential alias — together with those its Comparison carries.
The comparison is IS NOT NULL in every construction the planner performs, which correlates to nothing, but the struct permits any comparison. Reading only the operand would silently under-report the moment one appears, and an under-reported correlation is invisible: it does not fail, it produces an expression referencing an alias nothing supplies.
func (*ExistentialValuePredicate) GetExistentialAlias ¶
func (p *ExistentialValuePredicate) GetExistentialAlias() values.CorrelationIdentifier
GetExistentialAlias returns the QuantifiedObjectValue operand's correlation — the alias bound to the subquery. Mirrors Java's getQuantifierAlias().
type FieldAccessTrieNode ¶
type FieldAccessTrieNode struct {
// FieldName is the name of the field this node represents.
FieldName string
// Ordinal is the protobuf field ordinal.
Ordinal int
// Children, if non-nil, are the child trie nodes keyed by
// field name. A nil map means this is a terminal node.
Children map[string]*FieldAccessTrieNode
// TypeName is the terminal type string. Set only when
// Children is nil (leaf of the trie).
TypeName string
}
FieldAccessTrieNode is one node in the field-access trie that CompatibleTypeEvolutionPredicate carries. Each node either has children (keyed by field accessor) or a terminal type value.
Ports Java's CompatibleTypeEvolutionPredicate.FieldAccessTrieNode.
type IndexAvailability ¶
type IndexAvailability interface {
// IndexLastModifiedVersion reports the index's current
// lastModifiedVersion, and whether the store's metadata names it.
IndexLastModifiedVersion(name string) (version int, present bool)
// IsIndexReadable reports whether the index is strictly READABLE —
// Java's isReadable, which excludes READABLE_UNIQUE_PENDING even though
// it is scannable.
IsIndexReadable(name string) bool
}
IndexAvailability answers, for one live record store, the two questions a plan's index dependency turns on. Eval's context is opaque by interface (predicates.go:229-237), so this is how a caller that HAS a store supplies one — the record-store types live in a package this one cannot import.
present=false means the store's metadata does not name the index at all, which is Java's `!recordMetaData.hasIndex` leg (DatabaseObjectDependenciesPredicate.java:91-93).
type MergeResult ¶
type MergeResult struct {
// Range is the merged range. Never nil.
Range *ComparisonRange
// Residuals are the comparisons the range could not carry, in the order
// they were offered. Empty when everything merged.
Residuals []*Comparison
}
MergeResult carries the outcome of a Merge call: the merged range and the comparisons that could not be pushed into it. Java's ComparisonRange.MergeResult.
func MergeAll ¶
func MergeAll(comparisons []*Comparison) MergeResult
MergeAll folds a list of comparisons into one range from the empty range, accumulating the residuals — Java's ComparisonRange.mergeAll.
func (MergeResult) Complete ¶
func (m MergeResult) Complete() bool
Complete reports whether every offered comparison merged into the range.
type NonResidualPredicateError ¶
type NonResidualPredicateError struct {
Detail string
}
NonResidualPredicateError reports a predicate that cannot be converted into an executable filter. Java expresses the same condition as a `Verify.verify(!disjuncts.isEmpty())` inside `OrPredicate.of` (OrPredicate.java:439) — a thrown assertion, not a value — so the Go mapping is an error rather than a degenerate predicate. It matters that this is loud: the whole point of the conversion is that a predicate which cannot answer for a row must never reach a filter, and returning `OR()` here would hand the caller a predicate whose Eval is an unconditional FALSE.
func (*NonResidualPredicateError) Error ¶
func (e *NonResidualPredicateError) Error() string
type NotPredicate ¶
type NotPredicate struct {
Child QueryPredicate
// contains filtered or unexported fields
}
NotPredicate is the Kleene NOT of a single child. NOT UNKNOWN = UNKNOWN.
func (*NotPredicate) Children ¶
func (p *NotPredicate) Children() []QueryPredicate
func (*NotPredicate) Explain ¶
func (p *NotPredicate) Explain() string
func (*NotPredicate) GetCorrelatedTo ¶
func (p *NotPredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the child's correlations.
type OrPredicate ¶
type OrPredicate struct {
SubPredicates []QueryPredicate
// contains filtered or unexported fields
}
OrPredicate is the Kleene OR of children. Empty children yields FALSE (identity). A single TRUE child short-circuits to TRUE.
func (*OrPredicate) Children ¶
func (p *OrPredicate) Children() []QueryPredicate
func (*OrPredicate) Explain ¶
func (p *OrPredicate) Explain() string
func (*OrPredicate) GetCorrelatedTo ¶
func (p *OrPredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the union of all children's correlations.
type Placeholder ¶
type Placeholder struct {
// ParameterAlias uniquely identifies this placeholder in the
// candidate's parameter list.
ParameterAlias values.CorrelationIdentifier
// Value is the value expression being constrained (e.g. a
// FieldValue representing a column).
Value values.Value
// CompRange is the comparison range constraint on this
// placeholder. Empty range = unconstrained.
CompRange *ComparisonRange
}
Placeholder is a QueryPredicate representing a sargable parameter slot in a candidate expression tree. During index matching, the matching rules check whether query predicates can "fill" a placeholder. Mirrors Java's `com.apple.foundationdb.record.query.plan.cascades.predicates.Placeholder`.
A Placeholder carries:
- ParameterAlias: uniquely identifies this slot in the candidate's parameter list (maps to MatchCandidate.GetSargableAliases()).
- Value: the value expression being constrained (e.g. a FieldValue representing a column).
- CompRange: the comparison range constraint on this placeholder. An empty range means unconstrained.
Placeholder is a leaf predicate — it has no children.
func NewPlaceholder ¶
func NewPlaceholder(parameterAlias values.CorrelationIdentifier, value values.Value) *Placeholder
NewPlaceholder constructs a Placeholder with the given alias and value, and an initially empty ComparisonRange.
func (*Placeholder) Children ¶
func (*Placeholder) Children() []QueryPredicate
Children returns an empty slice — Placeholder is a leaf predicate.
func (*Placeholder) Eval ¶
func (*Placeholder) Eval(_ any) (TriBool, error)
Eval returns TriUnknown — placeholders are planning-time constructs and are never evaluated at runtime.
func (*Placeholder) Explain ¶
func (p *Placeholder) Explain() string
Explain renders a textual form: "Placeholder(alias, value)".
func (*Placeholder) GetComparisonRange ¶
func (p *Placeholder) GetComparisonRange() *ComparisonRange
GetComparisonRange returns the comparison range constraint.
func (*Placeholder) GetCorrelatedTo ¶
func (p *Placeholder) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the set of correlation identifiers this placeholder references: its parameter alias, the correlations of the constrained Value, and those of every comparison in its range.
The range comparisons count. A placeholder bound to a range whose comparand is itself correlated (a parameter compared against another quantifier's column) references that quantifier, and a caller that cannot see it will treat the placeholder as independent of a quantifier it actually needs.
func (*Placeholder) GetParameterAlias ¶
func (p *Placeholder) GetParameterAlias() values.CorrelationIdentifier
GetParameterAlias returns the alias that identifies this placeholder in the candidate's parameter list.
func (*Placeholder) GetValue ¶
func (p *Placeholder) GetValue() values.Value
GetValue returns the value expression being constrained.
func (*Placeholder) IsConstraining ¶
func (p *Placeholder) IsConstraining() bool
IsConstraining reports whether this placeholder has a non-empty range — i.e. whether it actually constrains the value.
func (*Placeholder) Negate ¶
func (p *Placeholder) Negate() QueryPredicate
Negate returns the placeholder itself — placeholders don't negate. They are structural slots, not boolean expressions.
func (*Placeholder) WithRange ¶
func (p *Placeholder) WithRange(cr *ComparisonRange) *Placeholder
WithRange returns a new Placeholder with the given comparison range. The original is not modified.
type PredicateWithValueAndRanges ¶
type PredicateWithValueAndRanges struct {
// contains filtered or unexported fields
}
PredicateWithValueAndRanges associates a Value with a set of RangeConstraints. The set represents a disjunction of range conjunctions — effectively a boolean predicate in DNF form on the associated Value.
Used primarily for index matching: on the query side to represent a sargable (search-argument-able) predicate, on the candidate side to represent column constraints.
Ports Java's `com.apple.foundationdb.record.query.plan.cascades.predicates.PredicateWithValueAndRanges`.
func NewPredicateWithValueAndRanges ¶
func NewPredicateWithValueAndRanges(value values.Value, ranges []*RangeConstraints) *PredicateWithValueAndRanges
NewPredicateWithValueAndRanges constructs a PredicateWithValueAndRanges.
func (*PredicateWithValueAndRanges) Children ¶
func (p *PredicateWithValueAndRanges) Children() []QueryPredicate
func (*PredicateWithValueAndRanges) Eval ¶
func (p *PredicateWithValueAndRanges) Eval(_ any) (TriBool, error)
func (*PredicateWithValueAndRanges) Explain ¶
func (p *PredicateWithValueAndRanges) Explain() string
Explain returns a human-readable representation.
func (*PredicateWithValueAndRanges) GetComparisons ¶
func (p *PredicateWithValueAndRanges) GetComparisons() []Comparison
GetComparisons returns all comparisons from all ranges, flattened.
func (*PredicateWithValueAndRanges) GetCorrelatedTo ¶
func (p *PredicateWithValueAndRanges) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the union of correlation identifiers from the value and all range constraints.
func (*PredicateWithValueAndRanges) GetRanges ¶
func (p *PredicateWithValueAndRanges) GetRanges() []*RangeConstraints
GetRanges returns the set of RangeConstraints (disjunction of range conjunctions).
func (*PredicateWithValueAndRanges) GetValue ¶
func (p *PredicateWithValueAndRanges) GetValue() values.Value
GetValue returns the Value associated with the range constraints.
func (*PredicateWithValueAndRanges) IsCompileTime ¶
func (p *PredicateWithValueAndRanges) IsCompileTime() bool
IsCompileTime reports whether all range constraints are compile-time evaluable.
func (*PredicateWithValueAndRanges) WithRanges ¶
func (p *PredicateWithValueAndRanges) WithRanges(ranges []*RangeConstraints) *PredicateWithValueAndRanges
WithRanges returns a new PredicateWithValueAndRanges with the given ranges, keeping the same Value.
func (*PredicateWithValueAndRanges) WithValue ¶
func (p *PredicateWithValueAndRanges) WithValue(v values.Value) *PredicateWithValueAndRanges
WithValue returns a new PredicateWithValueAndRanges with the given Value, keeping the same ranges.
type QueryPredicate ¶
type QueryPredicate interface {
// Children returns the immediate sub-predicates. Leaf
// predicates (ConstantPredicate, ComparisonPredicate, …)
// return an empty slice.
Children() []QueryPredicate
// Eval returns the predicate's truth value given an
// opaque evaluation context. Concrete eval context is
// impl-defined: ValuePredicate / ComparisonPredicate thread it
// into their operand Values' Evaluate; the boolean connectives
// thread it to their children; ConstantPredicate ignores it. A
// non-nil error signals a runtime evaluation failure (e.g. a
// type-mismatch comparison or an erroring child Value); the
// returned TriBool is TriUnknown in that case.
Eval(evalCtx any) (TriBool, error)
// Explain renders a parenthesised textual form suitable for
// debug + plan-diff output.
Explain() string
// this predicate and all its descendants reference. Each concrete
// type contributes its own correlations (Values, existential aliases,
// parameter aliases) plus the union of all children's correlations.
// Mirrors Java's QueryPredicate.getCorrelatedTo() which is transitive.
GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
}
QueryPredicate is the root of the predicate hierarchy. A QueryPredicate is a tree of boolean expressions with 3-valued logic semantics.
func EvaluatePredicateComparands ¶
func EvaluatePredicateComparands(p QueryPredicate) QueryPredicate
EvaluatePredicateComparands is SimplifyPredicateValues with values.EvaluateConstantComparand at the leaves: every constant composite becomes a literal. It is for a predicate STORED with literal comparands -- the sparse-index predicate, Java's IndexComparison taking `comparison.getComparand(null, null)` -- never for a query plan.
func ExistsValueToQueryPredicate ¶
func ExistsValueToQueryPredicate(ev *values.ExistsValue) QueryPredicate
ExistsValueToQueryPredicate is the bridge from the value-layer EXISTS (values.ExistsValue) to the predicate-layer EXISTS, mirroring Java's ExistsValue.toQueryPredicate() → ExistentialValuePredicate(child, NullComparison(NOT_NULL)). It lives in the predicates package because the values package cannot import predicates (import cycle: predicates imports values). The child must be a QuantifiedObjectValue.
func FindStructuralPredicate ¶
func FindStructuralPredicate(p QueryPredicate) (QueryPredicate, bool)
FindStructuralPredicate returns the first predicate in p's tree that is STRUCTURAL — an instruction to the planner's matching machinery rather than a test a row can answer — and reports whether one was found.
The three types are exactly the ones ToResidualPredicate converts, and they share a tell: each has an unconditional non-answer as its Eval, so none of them can ever contribute a TRUE.
- *ExistentialValuePredicate names the existential quantifier's alias. Once its subplan has been lowered to a FirstOrDefault, no physical row carries that alias.
- *PredicateWithValueAndRanges is an index search argument; its Eval is an unconditional TriUnknown.
- *Placeholder is a matching-time marker; its Eval is an unconditional TriUnknown. Java makes this a subtype of the sargable (Placeholder.java:48); Go's is a standalone struct, which is precisely why it has to be named here rather than caught by the sargable case.
This exists as an INVARIANT rather than as a fix in each rule because the failure it guards is invisible: a structural predicate in a RecordQueryPredicatesFilterPlan makes the filter reject every row and report success, which is indistinguishable from an empty table. Three separate rules build physical filters, and requiring each to remember the conversion is how two of them came to forget it.
func FlattenConjunction ¶
func FlattenConjunction(preds []QueryPredicate) []QueryPredicate
FlattenConjunction lifts every top-level AndPredicate in preds into the list, recursively, so the list IS the conjunction: `[And(a, And(b, c)), d]` is `[a, b, c, d]`. An AND under an OR or a NOT is that node's child and is left alone. Java's SelectExpression constructor applies this (SelectExpression.partitionPredicates → flattenPredicate(AndPredicate.class)), which is why a Java rule can read a Select's predicate list as its conjuncts; the expression constructors here establish the same invariant. Returns preds itself when nothing needed lifting, so an already-flat list keeps its identity and a constructor call allocates nothing.
func FoldComparisonMaybe ¶
func FoldComparisonMaybe(lhsValue values.Value, comp Comparison) QueryPredicate
FoldComparisonMaybe is Java's ConstantPredicateFoldingUtil.foldComparisonMaybe: the constant a comparison of lhsValue folds to over EFFECTIVE constants, or nil when it does not fold. IS [NOT] NULL is decided by a NULL or a NOT NULL operand; a binary comparison with a NULL side is NULL; EQUALS and NOT_EQUALS over two known literals (TRUE, FALSE, NULL) compare them; anything else, including a comparison of two non-boolean literals, does not fold.
func PartitionPredicates ¶
func PartitionPredicates(predicates []QueryPredicate) []QueryPredicate
PartitionPredicates ports SelectExpression.partitionPredicates: opaque predicates precede stable, value-equivalent groups of residuals and ranges.
func RebasePredicateChecked ¶
func RebasePredicateChecked(p QueryPredicate, aliases values.AliasMap) (QueryPredicate, error)
RebasePredicateChecked replaces correlation references in every embedded Value tree through the checked rewrite authority, then rebases the one correlation stored outside a Value (Placeholder.ParameterAlias). The whole predicate graph is invocation-local and atomic: an invalid FieldValue reconstruction returns an error and no partial predicate.
func ReplaceValues ¶
func ReplaceValues(p QueryPredicate, fn func(values.Value) values.Value) QueryPredicate
ReplaceValues applies a Value replacement function to all Value trees embedded in a predicate, rebuilding only the spine that changed. Ports Java's QueryPredicate.replaceValuesMaybe. Pointer-equality stable: returns p itself when nothing changed.
This is the EXPORTED home of the walk (the cascades package's replacePredicateValues delegates here): the translator bakes gated-join leg references at the seed with it, and the planner's rule-side callers share the identical spine so predicate-value rewrites can never diverge between the two layers.
func SimplifyPredicateValues ¶
func SimplifyPredicateValues(p QueryPredicate) QueryPredicate
SimplifyPredicateValues walks a QueryPredicate tree and returns a new tree with SimplifyValue applied to every Value operand reachable inside ComparisonPredicate / ValuePredicate leaves. Boolean connectives (AND / OR / NOT) recurse into their children.
Returns the input pointer unchanged when nothing folded — callers can rely on the pointer-equality short-circuit (`if out != p { ... }`) to detect "did anything change?".
It is the value half of Java's ValuePredicateSimplificationRule, which cascades.ConstantFoldingRules applies to each leaf inside the QueryPredicate-level fixpoint: `name = 1+2` becomes `name = 3`.
func ToResidualPredicate ¶
func ToResidualPredicate(p QueryPredicate) (QueryPredicate, error)
ToResidualPredicate returns a predicate equivalent to p that can be evaluated as a RESIDUAL — a filter applied to rows that have already been produced — rather than as an index search argument or an instruction to the matching machinery.
Ports Java's `QueryPredicate.toResidualPredicate()`: the interface default (`QueryPredicate.java:252-260`) and its overrides on the existential predicate (`ExistentialValuePredicate.java:107-109`) and the sargable (`PredicateWithValueAndRanges.java:483-492`). Java spells it as a default method; Go has no interface defaults, so it is a package-level function over the interface — the shape `IsTautology` and `ReplaceValues` already use.
Three predicate types cannot answer for a row, and all three have an unconditional non-answer as their Eval: `ExistentialValuePredicate` names an alias no physical row carries once its subplan is a FirstOrDefault, `PredicateWithValueAndRanges` is an index search argument (`Eval` → TriUnknown), and `Placeholder` is a matching-time marker (`Eval` → TriUnknown). Leaving any of them in a filter is not a slower plan, it is a wrong one: the filter drops the entire stream while reporting success.
Pointer-stable: a predicate needing no rewrite is returned as itself.
func ToResidualPredicates ¶
func ToResidualPredicates(preds []QueryPredicate) ([]QueryPredicate, error)
ToResidualPredicates converts a whole predicate list, the shape every filter-building rule needs. Java writes this as `predicates.stream().map(QueryPredicate::toResidualPredicate)` at each of its three filter sites (ImplementFilterRule.java:90, ImplementSimpleSelectRule.java:169, ImplementNestedLoopJoinRule.java:157); having one helper keeps Go from growing three spellings of it.
It is atomic: a failure returns no list rather than a partially converted one.
func TransformEmbeddedValues ¶
func TransformEmbeddedValues(p QueryPredicate, transform func(values.Value) values.Value) QueryPredicate
TransformEmbeddedValues applies transform once per complete embedded Value tree, not per interior node. An identity transform rebuilds no predicate nodes.
func TransformEmbeddedValuesChecked ¶
func TransformEmbeddedValuesChecked( p QueryPredicate, transform func(values.Value) (values.Value, error), ) (QueryPredicate, error)
TransformEmbeddedValuesChecked applies transform once to every complete Value tree owned by p. It does not independently revisit interior Value nodes: callers that need a recursive Value rewrite perform that recursion inside transform. Predicate rebuilding is invocation-local and atomic; the first error returns no predicate graph.
func TranslateLeafPredicates ¶
func TranslateLeafPredicates(p QueryPredicate, m values.TranslationMap) QueryPredicate
TranslateLeafPredicates applies a TranslationMap to every Value tree embedded in a predicate — the Go analog of Java's QueryPredicate.translateLeafPredicate (ValuePredicate.java:149: each predicate's embedded Value goes through Value.translateCorrelations). LEAF-ONLY by construction: the map fires on correlation-bearing leaves via values.TranslateCorrelations — never on interior nodes — and shares the exact predicate spine ReplaceValues uses, so the two rewrite families cannot diverge. Pointer-stable.
func TranslateLeafPredicatesChecked ¶
func TranslateLeafPredicatesChecked(p QueryPredicate, m values.TranslationMap) (QueryPredicate, error)
TranslateLeafPredicatesChecked is the atomic, error-bearing translation authority. A failed Value reconstruction returns no predicate graph; it never embeds a nil Value in an otherwise valid predicate or publishes a partially translated conjunction.
func WithAtomicity ¶
func WithAtomicity(p QueryPredicate, atomic bool) QueryPredicate
WithAtomicity copies a connective's optimization barrier; leaves are unchanged.
type RangeConstraints ¶
type RangeConstraints struct {
// contains filtered or unexported fields
}
RangeConstraints represents a conjunction of a compile-time evaluable range and a set of deferred (non-compile-time) ranges. Used during index matching to represent constraints on a single indexed column.
Ports Java's `com.apple.foundationdb.record.query.plan.cascades.predicates.RangeConstraints`.
The compile-time range is represented as a list of Comparisons that can be evaluated against literal values. Deferred ranges are Comparisons that reference correlation variables and can only be evaluated at runtime (but can still form part of an index scan prefix).
RangeConstraints can be converted to a ComparisonRange via AsComparisonRange() for backward compatibility with existing matching infrastructure.
func EmptyRangeConstraints ¶
func EmptyRangeConstraints() *RangeConstraints
EmptyRangeConstraints returns a RangeConstraints with no comparisons (matches everything).
func NewRangeConstraints ¶
func NewRangeConstraints(compilable []Comparison, deferred []Comparison) *RangeConstraints
NewRangeConstraints constructs a RangeConstraints from compile-time and deferred comparisons.
func (*RangeConstraints) AsComparisonRange ¶
func (r *RangeConstraints) AsComparisonRange() (*ComparisonRange, bool)
AsComparisonRange converts this RangeConstraints to a ComparisonRange by merging all comparisons. This is for backward compatibility with existing matching infrastructure that uses ComparisonRange.
It returns false when the constraints cannot be expressed as ONE ComparisonRange: the merge is total and reports what did not fit as residuals (Java's asMergedComparisonRange returns the range plus that list), but this signature has nowhere to hand them on, so `x = 5 AND x > 7` is refused rather than answered with the WEAKER `x = 5` — a caller filtering on the weaker range would return rows the constraints excluded. A caller that can carry residuals should call MergeAll on GetComparisons directly.
LATENT, and said so deliberately: this function has no non-test callers.
func (*RangeConstraints) Encloses ¶
func (r *RangeConstraints) Encloses(other *RangeConstraints) bool
Encloses proves containment of literal-bound ranges. As in Java RangeConstraints.encloses, deferred candidate constraints prevent a proof; deferred query constraints may only narrow its known range. Runtime-bound parameters are deliberately not evaluated here: their values would require a captured plan-cache constraint, not an unconditional implication proof.
func (*RangeConstraints) GetComparisons ¶
func (r *RangeConstraints) GetComparisons() []Comparison
GetComparisons returns all comparisons (compilable + deferred), cached after first computation.
func (*RangeConstraints) GetCompilableComparisons ¶
func (r *RangeConstraints) GetCompilableComparisons() []Comparison
GetCompilableComparisons returns the compile-time evaluable comparisons.
func (*RangeConstraints) GetCorrelatedTo ¶
func (r *RangeConstraints) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the set of correlation identifiers referenced by all comparisons in this RangeConstraints.
func (*RangeConstraints) GetDeferredRanges ¶
func (r *RangeConstraints) GetDeferredRanges() []Comparison
GetDeferredRanges returns the deferred (non-compile-time) comparisons.
func (*RangeConstraints) IsCompileTime ¶
func (r *RangeConstraints) IsCompileTime() bool
IsCompileTime reports whether all comparisons in this RangeConstraints can be evaluated at compile time (no deferred ranges, no correlation references).
func (*RangeConstraints) IsConstraining ¶
func (r *RangeConstraints) IsConstraining() bool
IsConstraining reports whether this RangeConstraints has any comparisons (compilable or deferred).
type RangeConstraintsBuilder ¶
type RangeConstraintsBuilder struct {
// contains filtered or unexported fields
}
RangeConstraintsBuilder builds a RangeConstraints incrementally.
func NewRangeConstraintsBuilder ¶
func NewRangeConstraintsBuilder() *RangeConstraintsBuilder
NewRangeConstraintsBuilder creates a new builder.
func (*RangeConstraintsBuilder) Add ¶
func (b *RangeConstraintsBuilder) Add(r *RangeConstraints)
Add intersects a range without reclassifying its compiled/deferred lanes.
func (*RangeConstraintsBuilder) AddComparisonMaybe ¶
func (b *RangeConstraintsBuilder) AddComparisonMaybe(c Comparison) bool
AddComparisonMaybe adds a comparison to the builder. Returns true if the comparison was added successfully; false when the comparison kind cannot bound a scan prefix (Java's Builder.addComparisonMaybe, RangeConstraints.java:787-797, gated on canBeUsedInScanPrefix).
func (*RangeConstraintsBuilder) Build ¶
func (b *RangeConstraintsBuilder) Build() *RangeConstraints
Build creates the RangeConstraints from accumulated comparisons.
type TemporalCarrierError ¶
TemporalCarrierError is a comparison operand that evaluated to a time.Time. DATE and TIMESTAMP values are canonical text, so this is an internal error: a time.Time compared as text or skipped would answer silently wrong.
func (*TemporalCarrierError) Error ¶
func (e *TemporalCarrierError) Error() string
type TriBool ¶
type TriBool *bool
TriBool is the SQL 3-valued logic result. A nil pointer is UNKNOWN; otherwise the bool value is true or false. Chose a pointer over a dedicated enum so downstream eval code can use `if result != nil && *result { ... }` without a custom type.
TriTrue / TriFalse / TriUnknown are the canonical tri-state constants. Matchers compare against these rather than constructing fresh pointers.
func AsConstant ¶
func AsConstant(p QueryPredicate) (TriBool, bool)
AsConstant returns (value, true) if p is a ConstantPredicate; (_, false) otherwise. Rule bodies use this as the canonical "is this a fold-able constant?" check, instead of open-coding type assertions.
type TypeMismatchError ¶
TypeMismatchError is returned when a comparison encounters incompatible types (e.g., int64 vs string). The executor surfaces it as SQLSTATE 22000 (CANNOT_CONVERT_TYPE), matching Java's SemanticException.
func (*TypeMismatchError) Error ¶
func (e *TypeMismatchError) Error() string
type UsedIndex ¶
type UsedIndex struct {
// Name is the index name.
Name string
// LastModifiedVersion is the metadata version at which the
// index was last modified, captured at plan creation time.
LastModifiedVersion int
}
UsedIndex captures the name and lastModifiedVersion of an index that a plan depends on. Ports Java's DatabaseObjectDependenciesPredicate.UsedIndex.
type ValuePredicate ¶
ValuePredicate wraps a boolean-typed Value as a predicate. The Value evaluates to bool (or nil for UNKNOWN); ValuePredicate.Eval maps that straight to TriBool. `SELECT ... WHERE is_active` where `is_active` is a boolean column or expression goes through this node after semantic analysis.
Returns UNKNOWN when the Value evaluates to nil (NULL) or to any non-bool type — the latter is a type-checking responsibility the semantic analyzer should have already caught; falling through to UNKNOWN keeps the runtime safe against analyzer gaps.
func NewValuePredicate ¶
func NewValuePredicate(v values.Value) *ValuePredicate
NewValuePredicate constructs a ValuePredicate.
func (*ValuePredicate) Children ¶
func (*ValuePredicate) Children() []QueryPredicate
func (*ValuePredicate) Explain ¶
func (p *ValuePredicate) Explain() string
func (*ValuePredicate) GetCorrelatedTo ¶
func (p *ValuePredicate) GetCorrelatedTo() map[values.CorrelationIdentifier]struct{}
GetCorrelatedTo returns the correlations from the carried Value.
Source Files
¶
- comparison_identity.go
- comparison_range.go
- comparisons.go
- compatible_type_evolution_predicate.go
- database_object_dependencies_predicate.go
- distance_rank_transform.go
- existential_value_predicate.go
- leaf_query_predicate.go
- partition.go
- placeholder.go
- predicate_correlation.go
- predicate_with_value_and_ranges.go
- predicates.go
- range_constraints.go
- range_enclosure.go
- rebase.go
- relop_eval.go
- replace_values.go
- semantic_equals.go
- semantic_hash.go
- simplifier_predicate_values.go
- structural_equal.go
- structural_hash.go
- structural_predicate.go
- to_residual_predicate.go