plans

package
v0.0.0-...-239813c Latest Latest
Warning

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

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

Documentation

Overview

Go extension — no Java equivalent.

Java's Cascades has no physical sort operator; RemoveSortRule eliminates the sort via index ordering or fails the query. This plan materializes the inner result and sorts in memory.

Package plans is the physical-plan ("RecordQueryPlan") hierarchy the Cascades planner emits after Batch A rules implement logical expressions as concrete query operators.

Mirrors Java's `com.apple.foundationdb.record.query.plan.plans` package. Java has 74 RecordQueryPlan classes; the seed ports the minimum set Batch A's first rules need:

  • RecordQueryScanPlan — primary-key scan over a record type.
  • RecordQueryFilterPlan — applies a QueryPredicate to an inner plan's row stream.
  • RecordQueryInMemorySortPlan — sorts an inner plan's row stream in memory (Go extension; Java's Cascades eliminates the sort via index ordering, RemoveSortRule/ImplementSortRule).

The seed deliberately omits Java's full surface (Execute method, PlanHashable, continuation handling, complex covering-index machinery) — those land as the rule chain that produces these plans starts consuming them. The seed is the type structure + node-info equality so PrimaryScanRule / ImplementFilterRule / ImplementInMemorySortRule have a target to yield into.

Why a separate sub-package vs cascades/expressions/: to mirror Java's package layout, so code review across the two languages stays tractable.

This used to say something stronger and WRONG — that "physical and logical plan trees live in different namespaces in Java", so a RecordQueryPlan is not a RelationalExpression. Java says the opposite:

QueryPlan<T> extends PlanHashable, RelationalExpression  (QueryPlan.java:51)
RecordQueryPlan extends QueryPlan<…>              (RecordQueryPlan.java:73)

Java separates the PACKAGE and unifies the HIERARCHY; the old comment conflated the two. That misreading is where the 23-file physical_*_wrapper.go layer came from — adapters existing only to present a plan as an expression — and with it the nil-inner "shell" bug class, since a wrapper and its wrapped plan each stored the parent->child edge and could disagree. RecordQueryPlan now embeds RelationalExpression directly (RFC-183 P5).

Index

Constants

This section is empty.

Variables

CostedPlanPrototypes is one typed-nil instance of every plan that answers the CostedPlan contract. It serves two jobs at once: the slice's element type is the compile-time completeness check (a plan missing either method will not go in), and the slice itself is what the derivation-agreement and logical/physical parity tests ENUMERATE.

Enumeration is what keeps those tests from passing vacuously. A hand-written pairing table checked only against itself stops testing anything the day operator 38 is added; driven off this list, an operator with no table entry fails with a message naming it, so an unpaired arm gets an explicit listed reason rather than silence.

Typed nils are safe here: every ProvenCardinalities implementation is nil-receiver tolerant, which the enumeration tests exercise directly.

Functions

func EqualityBoundCoordinateClaimsOwnOrder

func EqualityBoundCoordinateClaimsOwnOrder(cr *predicates.ComparisonRange) bool

EqualityBoundCoordinateClaimsOwnOrder answers a DIFFERENT question from EqualityPinsSinglePhysicalKey, and the two must never be substituted for one another — conflating them is precisely the defect this pair replaces.

EqualityPinsSinglePhysicalKey: may LATER coordinates claim order THROUGH
                               this one? (the SUFFIX question)
this predicate:                may THIS coordinate claim ITS OWN order?
                               (the SELF question)

A signed-zero float equality answers NO to the first and YES to the second. It answers no to the first because it spans two physical keys, so a later coordinate restarts at the block boundary: over rows (-0.0, 9) and (+0.0, 1), `WHERE v = 0 ORDER BY w` returns [9 1]. That termination is inviolable and stays exactly as it was.

It answers yes to the second on ONE ground, the PHYSICAL ENUMERATION, and only that: the executor's range set opens the two signed-zero blocks in KEY ORDER and reverses them wholesale for a reverse scan, so the coordinate is genuinely ordered in whichever direction the scan runs. DESC and mid-scan resume rest on the same fact. Because the ground is an enumeration order and not an absence of order, the claim it supports is SORTED and DIRECTIONAL.

Do NOT reason from tie-class vacuity here. The tempting alternative — "the equality admits one logical value, so any permutation satisfies ORDER BY, which settles ASC by itself" — is FALSE at this coordinate, and believing it produced a wrong answer. It presumes one comparator. There are TWO, and they disagree on signed zeros BY DESIGN: predicates.Comparison.Eval checks IEEE equality, so -0.0 == +0.0 and both rows are admitted; values.CompareFloat64 (faithful to java.lang.Double.compare, and to FDB tuple order) ranks -0.0 BELOW +0.0. The admitted rows are therefore TWO distinct ORDER BY values, not one tie class. (The NaN tie class elsewhere in this file IS genuine — there CompareFloat64 canonicalizes every payload to one value, so both comparators agree. The reasoning is sound for NaN and unsound for signed zeros; the difference is which comparators agree, so it must be checked, never assumed.)

The consequence is that the claim is DIRECTIONAL, never FIXED. A caller that records this coordinate as FIXED — order-free, hence satisfying any requested direction — elides the sort on `WHERE z = 0.0 ORDER BY z DESC` and answers it from a FORWARD scan. Measured, that returned the zero blocks ascending as [7 9 1 3] where the correct answer is [3 1 9 7]. HintRichOrdering binds it SORTED for that reason, and TestFDB_SignedZeroEqualityDoesNotOrderThePKSuffix/bound_column_descending pins it; its ascending sibling stays green either way and proves nothing.

NaN does not intrude here the way it does for an unbound or range-bound float coordinate: an equality against zero admits no NaN at all, so the two disjoint NaN blocks are simply out of range.

func EqualityPinsSinglePhysicalKey

func EqualityPinsSinglePhysicalKey(cr *predicates.ComparisonRange) bool

EqualityPinsSinglePhysicalKey reports whether cr binds its coordinate to ONE physical key — the property that makes the coordinate FIXED rather than sorted, so it claims no order of its own and the columns after it remain claimable.

This is the SINGLE AUTHORITY on that question. Two callers derive an ordering claim from a key-column sequence and must agree column for column: equalityPrefixLen here on the plan side, and the sargable candidates' ComputeMatchedOrderingParts on the cascades side. A second hand-rolled copy of the rule is how the two derivations drift apart and classify the same column differently — which is exactly the defect this consolidation removes, where one side exempted an equality-bound float and the other terminated on it, costing every affected query an index intersection or a materialized sort it did not need.

An equality is NOT enough on its own. A zero-valued FLOAT/DOUBLE equality pins no single key: the executor widens it to span both signed zeros (-0.0 and +0.0 are IEEE-equal but pack to distinct adjacent keys), so the scan covers TWO physical prefixes and every column after it RESETS at the boundary.

Counting that as an equality claimed the suffix was globally ordered and let the planner drop a required sort: over rows (-0.0, 9) and (+0.0, 1), `WHERE v = 0 ORDER BY w` returned [9 1] unsorted, and `... LIMIT 1` returned the wrong row entirely.

Such a range is treated like an inequality — it does not pin, so the prefix stops there. A non-equality leading comparison already trims nothing, so `v` stays in the ordering (it IS ordered: -0.0 sorts immediately before +0.0) while the suffix no longer claims an order the scan does not provide. A nil range is an ABSENT binding, not an equality — it pins nothing. The check is here rather than at the call sites because one of them reads a parameter-binding map, where a miss yields nil and IsEquality would panic.

func EqualityPinsSinglePhysicalKeyOnColumn

func EqualityPinsSinglePhysicalKeyOnColumn(cr *predicates.ComparisonRange, columnCouldBeFloat bool) bool

EqualityPinsSinglePhysicalKeyOnColumn is EqualityPinsSinglePhysicalKey for a caller that knows the INDEXED COORDINATE's type — the one fact the range alone cannot supply, and the one couldBeFloatOperand documents as the right discriminator it did not have.

The operand's declared type is not a usable proxy for it. An operand carries FLOAT only when the literal was coerced to the column; an IN-list binding reaches here as an UNKNOWN-typed correlation, and couldBeFloatOperand answers "not a float" for it. On an INT column that answer is right and load-bearing (it is what keeps an untyped IN-join binding's ascending claim). On a FLOAT column it is wrong, and wrong in the unsound direction: the binding can be zero at runtime, the executor widens the probe across both signed-zero blocks, and the coordinate pins no single key.

Splitting the question by COLUMN type keeps both answers: an int coordinate always pins (it has no signed zero to widen, whatever the operand), and a float coordinate pins only when the operand is a constant that is provably nonzero.

MEASURED, this is the whole of the InUnion defect. `e IN (5, 7, 0)` over a FLOAT column plans InUnion over a per-binding leg that advertises PK order. The zero binding widens at runtime to the -0.0 and +0.0 blocks, so that leg emits its +0.0 rows only after all of its -0.0 rows; the ordered merge reads one row of lookahead per leg, so those rows land after the entire result. `ORDER BY id` returned [4 17 20 26 29 30 32 42 45 47 69 103 119 14 80] — sorted except for the two +0.0 rows, 14 and 80, appended at the end.

This DIVERGES from Java, and the divergence is systematic rather than a patch over one Java slip. Java derives its ordering prefix from scanComparisons.getEqualitySize() with no signed-zero exemption anywhere, in four places built the identical way (4.12.11.0):

ValueIndexLikeMatchCandidate.java:166
WindowedIndexScanMatchCandidate.java:363
VectorIndexScanMatchCandidate.java:345
AggregateIndexMatchCandidate.java:340

all of them `for (i = scanComparisons.getEqualitySize(); i < …; i++)`. So Java makes the same unsound claim on every one of those candidate kinds, and the query above reproduces against it. Citing a single site would read as a local bug worth patching around; four identical sites say Go is knowingly declining a Java-wide behaviour, which is the claim DIVERGENCES.md has to carry.

func Equals

func Equals(a, b RecordQueryPlan) bool

Equals walks two plan trees and reports semantic equality — node-info match plus pairwise child equality. The plans seed doesn't have alias-aware comparison (no Quantifiers in the physical layer); positional pairing only.

Returns true if both nil.

func EvaluateContinuableWithoutDuplicates

func EvaluateContinuableWithoutDuplicates(p RecordQueryPlan) bool

EvaluateContinuableWithoutDuplicates is Java's ContinuableWithoutDuplicatesProperty.evaluate(plan).

func NestedLoopJoinUniqueKeyConjuncts

func NestedLoopJoinUniqueKeyConjuncts(p *RecordQueryNestedLoopJoinPlan) (int, bool)

NestedLoopJoinUniqueKeyConjuncts reports how many of p's own join-predicate conjuncts are consumed by a full equality bind on the inner leg's own UNIQUE key — the primary key of a bare scan, or the key columns of a declared-UNIQUE index scan. Exported so cascades/planning_cost_model.go's combineConcreteCost can reuse the identical detection for its own RecordQueryNestedLoopJoinPlan arm (both call sites must feed properties.NestedLoopJoinCost the SAME proof, or the concrete join-ordering comparison and the memo's HintCost would rank the identical plan two different ways).

This is the join-predicate analogue of isProvablePointProbe, applied exactly where isProvablePointProbe itself cannot fire: a materialized RecordQueryNestedLoopJoinPlan's inner leg is executed RAW and un-parameterized (NestedLoopJoinCost's own doc comment — the inner's own ScanComparisons carry no trace of the join predicate at all), so the equality only becomes visible in p's OWN predicate list, evaluated pairwise by the join itself. A FlatMap's correlated inner instead pushes the SAME equality down as a bound scan comparison, which is exactly what isProvablePointProbe already recognizes — this function recognizes the materialized join's OWN residual-predicate form of the identical shape.

Fails closed (0, false) on anything not specifically recognized — a non-unique index, a composite/nested (non-flat) PK component, a conjunct under OR/NOT, or a predicate binding only SOME of the key's columns. Under-detecting only forgoes the correction (today's flat FilterSelectivity fallback remains exactly as before); over-detecting would let a non-selective join masquerade as a point probe.

Also fails closed on JoinFullOuter: uniqueness caps only the MATCHED (outer, inner) pairs at one row each — it says nothing about the inner rows FULL OUTER additionally preserves when they matched no outer row at all, so a 10-row outer against a 1000-row inner cannot be capped to 10 the way an INNER join's equivalent bind can. JoinInner and JoinLeftOuter both still take the correction: LEFT OUTER already preserves every outer row exactly once (matched-or-NULL-padded) when the inner key is unique — 0 or 1 inner matches per outer row — so its true cardinality is already outerCard, same as INNER. JoinCross carries no join-predicate conjuncts to bind a key with in the first place, so it is excluded by omission rather than needing its own reasoning. Go has no separate JoinRightOuter: RIGHT JOIN is normalized to LEFT OUTER with outer/inner swapped at plan-construction time (cascades_translator.go), so that LEFT OUTER reasoning already covers it.

func OrdinalLayoutRequirementsEqual

func OrdinalLayoutRequirementsEqual(left, right OrdinalLayoutRequirement) bool

OrdinalLayoutRequirementsEqual reports whether two admitted requirements describe the same compatibility class. Exact requirements compare by the immutable layout value rather than wrapper identity, so independently built pass-through parents over the same physical layout converge when their requirements are accumulated in the memo. Source requirements compare by their immutable RequiredBindings identity: that is deliberately conservative because RequiredBindings does not expose its owner-current handle, and treating two independently collected manifests as equal without that handle would erase a potentially significant carrier distinction. Foreign, malformed and typed-nil views are never equal.

func PKScanOrdering

func PKScanOrdering(plan *RecordQueryScanPlan) properties.Ordering

PKScanOrdering returns a primary scan's PK ordering. Shared with the data-access path's plan-backed leaf, which memoizes a SARGed PK scan.

PK positions bound by an equality comparison do not consume a sort position: mirrors Java's ValueIndexLikeMatchCandidate.computeOrderingFromScanComparisons, whose equality-bound prefix (i < scanComparisons.getEqualitySize()) only populates the binding map with Binding.fixed entries and is never appended to orderingSequenceBuilder — the ordering sequence starts at the first non-equality-bound key. Without this, a per-binding equality scan (id Fixed) and an unbound scan over the same PK columns (id Sorted-ascending) report the identical Keys, so plan partitioning (expression_partition.go's orderingsEqual) cannot tell them apart and co-partitions them. Compare RecordQueryScanPlan.HintRichOrdering below, which already carries this distinction via FixedBinding/SortedBinding but is not consulted by plain-ordering partitioning.

func PlanHash

func PlanHash(p RecordQueryPlan) uint64

PlanHash computes a deterministic hash of the entire plan tree. The hash combines each node's HashCodeWithoutChildren with its structural position (depth-first traversal order). Two plans with the same tree shape and same node-info hash to the same key.

Consumed by plan logging (PlanGenerationInfo.PlanHash — the plan's identity in observability output). In-memory only: the plan cache is keyed by normalized SQL text, and no continuation or wire artifact embeds this hash, so its value may change across releases (RFC-176 P2 did) without compatibility impact.

func QuantifierOverPlan

func QuantifierOverPlan(child RecordQueryPlan) expressions.Quantifier

QuantifierOverPlan wraps a child plan in the Quantifier a parent plan stores it as — the Go spelling of Java's `Quantifier.physical( call.memoizePlan(childPlan))`.

StageCanonical, not StagePlanned: the stage records how far the PLANNER has processed a reference and is a separate decision from which member set the expression belongs in (see FinalOfAtStage). A plan's child belongs in the FINAL set — it is a plan — but stamping StagePlanned here would change what ExploreGroupTask does with the reference.

Returns the zero Quantifier for a nil child so a leaf-shaped construction does not fabricate an empty reference.

func QuantifiersOverPlans

func QuantifiersOverPlans(children []RecordQueryPlan) []expressions.Quantifier

QuantifiersOverPlans is QuantifierOverPlan across an N-ary plan's child list — the Go spelling of Java's `children.stream().map(c -> Quantifier.physical(call.memoizePlan(c)))`.

ORDER IS LOAD-BEARING and preserved exactly. Several of the plans that use this report ChildrenAsSet — Union, Intersection, MergeSortUnion — but that flag is about when two EXPRESSIONS are equivalent, not about whether this plan may reshuffle its own legs: Comparator indexes its reference plan by position, Selector picks by position, and every Explain renders legs in order. Index i in must stay index i out.

A nil child yields the zero Quantifier, matching QuantifierOverPlan, so a list containing one round-trips back to a nil at the same position rather than shrinking the arity.

func Size

func Size(p RecordQueryPlan) int

Size returns the total node count of the plan tree rooted at `p`, including `p` itself. Returns 0 for nil.

func TrimmedPKSuffix

func TrimmedPKSuffix(columnNames, pkColumnNames []string) []string

TrimmedPKSuffix returns the primary-key columns not already present in the index key columns, in PK order. Ports Java's Index.trimPrimaryKey semantics as used by ValueIndexExpansionVisitor.fullKey: PK components that appear in the index key are trimmed, the remainder is appended after the index key.

func UnableToTranslate

func UnableToTranslate(_ values.Value, _, _ values.CorrelationIdentifier) (values.Value, bool)

UnableToTranslate is a TranslateValueFunction that always fails (returns false). Used when no translation is possible.

func Walk

func Walk(p RecordQueryPlan, visit func(RecordQueryPlan) bool)

Walk invokes `visit` on `p` and (if visit returns true) recursively on every reachable RecordQueryPlan via GetChildren. Returning false from `visit` short-circuits the walk for that subtree (siblings + ancestors continue).

Counterpart to expressions.Walk for the logical side.

Types

type ContinuableWithoutDuplicatesVisitor

type ContinuableWithoutDuplicatesVisitor struct{}

ContinuableWithoutDuplicatesVisitor is Java's ContinuableWithoutDuplicatesPropertyVisitor: a per-plan-type override point over a default that recurses into children.

func (ContinuableWithoutDuplicatesVisitor) Visit

Visit reports whether the plan tree rooted at p can be resumed from a continuation without re-emitting an already-emitted row.

Java's visitor short-circuits by returning false from an overridden arm. Go splits the same logic in two so that a per-node verdict can never accidentally skip the subtree: selfContinuableWithoutDuplicates answers for THIS NODE ONLY, and the children are always folded in here. A node that is itself safe but sits over an unsafe child is unsafe, which is what Java's fromChildren default expresses.

type CostedPlan

type CostedPlan interface {
	properties.CostHinter
	properties.CardinalityProver
}

CostedPlan is the pair of questions the cost model asks every physical plan: what does it COST, and what does it PROVE about its own row count. They are one interface deliberately (RFC-195). The six impossible cost estimates that RFC exists to correct each accumulated because a plan could answer the first without the second — "this operator structurally guarantees a row" lived in a different file from "this operator costs in*0.7", and nothing required the two to agree, or even to both exist.

Registering a plan as one pair rather than two independent assertions means a new operator cannot gain a cost formula while silently proving nothing: the single line that registers it demands both, at compile time.

type DfsTraversalStrategy

type DfsTraversalStrategy int

DfsTraversalStrategy selects pre-order vs post-order traversal for the recursive DFS join.

const (
	DfsPreorder DfsTraversalStrategy = iota
	DfsPostorder
)

func (DfsTraversalStrategy) String

func (s DfsTraversalStrategy) String() string

type DistinctProofStampable

type DistinctProofStampable interface {
	RecordQueryPlan
	DistinctProofStamped
	// WithDistinctProofIndexName returns a shallow copy carrying the proof.
	WithDistinctProofIndexName(indexName string) RecordQueryPlan
}

DistinctProofStampable is DistinctProofStamped plus the struct-copy setter the eliding rule uses, in the shape WithStrictlySorted already established for stamping a proved planning fact onto a plan node.

The stamp is IDENTITY-BEARING — every carrier folds it into structuralKey. The tempting analogy is RecordQueryProjectionPlan.aliasMinted, which is deliberately excluded, and the analogy fails in the direction that matters: aliasMinted is a display tag, so two plans differing only in it compute identical rows and splitting the memo group would buy nothing. This stamp is a PROVED FACT THAT LICENSED THE PLAN'S SHAPE — one of the two plans is correct only while an index stays READABLE and the other is correct unconditionally, so they are not interchangeable. If the stamp did not split the group, the eliding rule's stamped copy would collapse into the unstamped original already in the memo, the survivor could be the unstamped one, and the dependency would vanish silently — which is exactly the unguarded elision the stamp exists to prevent.

The cost is stated rather than hidden: the memo can hold a stamped and an unstamped member for the same physical work, costing identically. One extra group member on one query shape against a wrong-answer bug is not a close trade.

type DistinctProofStamped

type DistinctProofStamped interface {
	GetDistinctProofIndexName() string
}

DistinctProofStamped is any physical plan that can report the secondary UNIQUE index whose uniqueness licensed eliding a DISTINCT above it. The empty string means the plan carries no such proof, which is the overwhelmingly common case: the elision is licensed by the distinct-records property or by primary-key coverage on every other shape, and neither stamps.

type FetchIndexRecords

type FetchIndexRecords int

FetchIndexRecords governs how to interpret the primary key of an index entry when fetching the base record. Mirrors Java's `RecordQueryFetchFromPartialRecordPlan.FetchIndexRecords` enum.

const (
	// FetchIndexRecordsPrimaryKey fetches the base record by its
	// primary key (the standard path).
	FetchIndexRecordsPrimaryKey FetchIndexRecords = iota
	// FetchIndexRecordsSyntheticConstituents fetches synthetic record
	// constituents (for synthetic/joined record types).
	FetchIndexRecordsSyntheticConstituents
)

type InSourceKind

type InSourceKind int

InSourceKind distinguishes the three Java InJoin subclasses.

const (
	InSourceValues    InSourceKind = iota // static value list (InValuesJoinPlan)
	InSourceParameter                     // runtime parameter binding (InParameterJoinPlan)
	InSourceComparand                     // comparand from correlated subquery (InComparandJoinPlan)
)

type IndexScanCarrier

type IndexScanCarrier interface {
	RecordQueryPlan

	// GetIndexPlan returns the index scan this node reads entries from. For a
	// bare index scan that is the node itself; for a covering scan it is the
	// wrapped field.
	GetIndexPlan() *RecordQueryIndexPlan
	// contains filtered or unexported methods
}

IndexScanCarrier is the plan-shaped answer to a hazard RFC-220 created structurally: a covering index scan HOLDS its index scan as a plain struct field, GetChildren returns nil, and so `plans.Walk` never descends into it. Every `case *RecordQueryIndexPlan` / `.(*RecordQueryIndexPlan)` written before RFC-220 is therefore blind to a covering scan BY CONSTRUCTION, and the access path now emits Fetch(Covering(IndexScan)) for every index-backed access — so the blindness is the ordinary case, not an exotic one.

The failure mode is what makes this a type rather than a convention. A miss does not raise; it answers "there is no index scan here", which downstream reads as "no comparison ranges", i.e. as an UNRESTRICTED scan — the expensive and, at two sites already found, the WRONG direction (an unstamped RecordConstructorValue evaluating name-keyed; a nil probed outer type licensing a name-keyed binding the probe exists to forbid).

The method set is deliberately ONE method. Everything a blind site was reading — scan comparisons, key component types, column names, reverseness — is a fact ABOUT THE INDEX SCAN, and the covering plan answers each by delegating to the very scan this returns. Restating those facts on the interface would create a second surface that must be kept in step with the first, and the day they drift the miss is silent again. One accessor, and every fact read off the thing it returns, keeps them in step by construction.

The interface is SEALED by an unexported method. Both implementations live in this package, and sealing is not decoration: RecordQueryAggregateIndexPlan also carries a `GetIndexPlan() *RecordQueryIndexPlan` and would otherwise satisfy this interface structurally — while emitting one row per GROUP, not one row per entry. A caller asking "what index scan does this node read entries from" and silently getting an aggregate plan's inner would be the same class of quiet wrong answer this type exists to remove.

type JoinType

type JoinType int

JoinType distinguishes inner vs outer vs cross joins.

const (
	JoinInner JoinType = iota
	JoinLeftOuter
	JoinCross

	// JoinFullOuter — FULL OUTER JOIN: every left row (matched or
	// NULL-padded right) plus every right row that matched no left row
	// (NULL-padded left). Go-only query extension; Java's SQL layer has
	// no outer joins. Appended (not inserted) to keep prior iota values
	// stable. Implemented only by the materialized nested-loop cursor,
	// never the correlated FlatMap path (which cannot observe global
	// inner-match state).
	JoinFullOuter
)

func (JoinType) String

func (jt JoinType) String() string

type KeysSource

type KeysSource interface {
	// GetPrimaryKeys returns the list of primary keys to load.
	GetPrimaryKeys() []tuple.Tuple
	// MaxCardinality returns the maximum number of records this
	// source can produce, or -1 if unknown.
	MaxCardinality() int
	// Equals reports equality with another KeysSource.
	Equals(other KeysSource) bool
	// String returns a human-readable label.
	String() string
}

KeysSource provides primary keys for RecordQueryLoadByKeysPlan. Mirrors Java's RecordQueryLoadByKeysPlan.KeysSource interface.

type OrdinalAddressingMode

type OrdinalAddressingMode uint8

OrdinalAddressingMode states whether one evaluation program retains local source-window roots or has been fully reanchored to its carrier.

const (
	OrdinalAddressingInvalid OrdinalAddressingMode = iota
	OrdinalAddressingSourceBound
	OrdinalAddressingCarrierBound
)

type OrdinalEvaluationProgram

type OrdinalEvaluationProgram interface {
	Layout() values.OrdinalLayout
	RequiredBindings() values.RequiredBindings
	AddressingMode() OrdinalAddressingMode
	// contains filtered or unexported methods
}

OrdinalEvaluationProgram pairs one evaluation layout with the exact origin manifest and addressing mode used by its retained Values.

func NewOrdinalEvaluationProgram

func NewOrdinalEvaluationProgram(
	layout values.OrdinalLayout,
	required values.RequiredBindings,
	mode OrdinalAddressingMode,
) (OrdinalEvaluationProgram, error)

NewOrdinalEvaluationProgram validates a complete physical evaluation phase.

type OrdinalLayoutAvailabilityCode

type OrdinalLayoutAvailabilityCode uint8

OrdinalLayoutAvailabilityCode classifies why a plan cannot provide a concrete ordinal layout. The dynamic-carrier case is a valid plan that must be refined before ordinal evaluation; malformed-base means construction was bypassed and is never a compatible physical alternative.

const (
	OrdinalLayoutAvailabilityInvalid OrdinalLayoutAvailabilityCode = iota
	OrdinalLayoutDynamicCarrier
	OrdinalLayoutMalformedPlan
)

type OrdinalLayoutRequirement

type OrdinalLayoutRequirement interface {
	SatisfiedBy(values.OrdinalLayout) (bool, error)
	// contains filtered or unexported methods
}

OrdinalLayoutRequirement is a sealed physical input requirement.

func RequireExactLayout

func RequireExactLayout(layout values.OrdinalLayout) (OrdinalLayoutRequirement, error)

RequireExactLayout constructs a carrier-bound requirement.

func RequireSources

func RequireSources(required values.RequiredBindings) (OrdinalLayoutRequirement, error)

RequireSources constructs a requirement from a values-owned binding-origin manifest. Only its local window sources participate in compatibility.

type OrdinalLayoutUnavailableError

type OrdinalLayoutUnavailableError struct {
	Code OrdinalLayoutAvailabilityCode
}

OrdinalLayoutUnavailableError is the typed, stable failure returned by ProvidedOutputLayout when no concrete layout can be published. It follows the repository's error-type contract rather than a message-only sentinel.

func (*OrdinalLayoutUnavailableError) Error

type OrdinalPhysicalProperties

type OrdinalPhysicalProperties interface {
	RequiredInputLayouts() []OrdinalLayoutRequirement
	EvaluationPrograms() []OrdinalEvaluationProgram
	ProvidedOutputLayout() values.OrdinalLayout
	// contains filtered or unexported methods
}

OrdinalPhysicalProperties is the immutable provided/required layout view of one physical plan. It is deliberately separate from logical identity.

func AsOrdinalPhysicalProperties

func AsOrdinalPhysicalProperties(value any) (OrdinalPhysicalProperties, bool)

AsOrdinalPhysicalProperties exact-recognizes only plans-owned views.

func NewOrdinalPhysicalProperties

func NewOrdinalPhysicalProperties(
	required []OrdinalLayoutRequirement,
	programs []OrdinalEvaluationProgram,
	provided values.OrdinalLayout,
) (OrdinalPhysicalProperties, error)

NewOrdinalPhysicalProperties constructs a complete physical-property view.

type ParameterKeySource

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

ParameterKeySource gets primary keys from a named parameter. Mirrors Java's ParameterKeySource inner class.

func NewParameterKeySource

func NewParameterKeySource(parameter string) *ParameterKeySource

NewParameterKeySource constructs a parameter-bound key source.

func (*ParameterKeySource) Equals

func (s *ParameterKeySource) Equals(other KeysSource) bool

Equals compares parameter names.

func (*ParameterKeySource) GetParameter

func (s *ParameterKeySource) GetParameter() string

GetParameter returns the parameter name.

func (*ParameterKeySource) GetPrimaryKeys

func (s *ParameterKeySource) GetPrimaryKeys() []tuple.Tuple

GetPrimaryKeys always returns nil — the actual keys come from the evaluation context at execution time.

func (*ParameterKeySource) MaxCardinality

func (s *ParameterKeySource) MaxCardinality() int

MaxCardinality returns -1 (unknown).

func (*ParameterKeySource) String

func (s *ParameterKeySource) String() string

String renders the parameter reference.

type PlanExprBase

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

PlanExprBase supplies the RelationalExpression methods that are identical across every plan type. Embed it; override anything a specific plan needs to answer differently (a set-op overrides ChildrenAsSet, a correlating operator overrides CanCorrelate and GetCorrelatedToWithoutChildren).

resultValue is populated by the owning plan's fallible constructor. Keeping it here gives plans that merely pass through a child one stable result identity without forcing every such plan to repeat a field. A zero value is intentionally invalid: struct literals that bypass construction no longer receive an untyped, freshly-minted compatibility QOV.

func (PlanExprBase) CanCorrelate

func (PlanExprBase) CanCorrelate() bool

CanCorrelate reports whether this operator anchors a correlation between its children. False for the physical operators that simply consume their input; the join-shaped plans override.

func (PlanExprBase) ChildrenAsSet

func (PlanExprBase) ChildrenAsSet() bool

ChildrenAsSet reports whether the children are commutative. False by default; the set operations override.

func (PlanExprBase) GetCorrelatedToWithoutChildren

func (PlanExprBase) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren returns the correlations this node's own information depends on. Empty by default — a plan that carries predicates or a result value referencing an outer quantifier must override, or correlation-driven rules will misclassify it.

func (PlanExprBase) GetQuantifiers

func (PlanExprBase) GetQuantifiers() []expressions.Quantifier

GetQuantifiers returns no quantifiers.

This is honest rather than lazy at this step: a plan's children really are raw RecordQueryPlan pointers right now, so there are no quantifiers to report, and synthesising throwaway ones per call would invent Reference identities that nothing else shares. Step 2 gives each plan real quantifier storage and this method goes away in favour of per-type accessors.

Nothing traverses plans as expressions yet, so reporting none changes no behaviour today.

func (PlanExprBase) GetResultValue

func (b PlanExprBase) GetResultValue() values.Value

GetResultValue returns the exact, stable Value admitted by the owner constructor. It never resolves on demand and never mints a correlation.

func (PlanExprBase) OrdinalPhysicalProperties

func (b PlanExprBase) OrdinalPhysicalProperties() (OrdinalPhysicalProperties, error)

OrdinalPhysicalProperties returns the immutable physical-property view admitted atomically with this plan's result Value. Dynamic exact carriers do not invent an unknown layout/property; zero or bypass-constructed bases are malformed in the same typed way as ProvidedOutputLayout.

func (PlanExprBase) ProvidedOutputLayout

func (b PlanExprBase) ProvidedOutputLayout() (values.OrdinalLayout, error)

ProvidedOutputLayout returns the immutable layout admitted atomically with the result Value. Plan reconstruction either retains this layout for an output-producing node or rebuilds the base from its replacement input.

type PlanSelector

type PlanSelector interface {
	// SelectPlan picks the index of the plan to execute.
	SelectPlan(plans []RecordQueryPlan) int
	// Equals reports equality with another PlanSelector.
	Equals(other PlanSelector) bool
	// String returns a human-readable label.
	String() string
}

PlanSelector selects one child plan index from a list at runtime. Mirrors Java's PlanSelector interface.

type PrimaryKeysKeySource

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

PrimaryKeysKeySource is a concrete list of primary keys. Mirrors Java's PrimaryKeysKeySource inner class.

func NewPrimaryKeysKeySource

func NewPrimaryKeysKeySource(primaryKeys []tuple.Tuple) *PrimaryKeysKeySource

NewPrimaryKeysKeySource constructs a key source from a list of primary key tuples.

func (*PrimaryKeysKeySource) Equals

func (s *PrimaryKeysKeySource) Equals(other KeysSource) bool

Equals compares key lists.

func (*PrimaryKeysKeySource) GetPrimaryKeys

func (s *PrimaryKeysKeySource) GetPrimaryKeys() []tuple.Tuple

GetPrimaryKeys returns the key list.

func (*PrimaryKeysKeySource) MaxCardinality

func (s *PrimaryKeysKeySource) MaxCardinality() int

MaxCardinality returns the list length.

func (*PrimaryKeysKeySource) String

func (s *PrimaryKeysKeySource) String() string

String renders the key list.

type RecordQueryAggregateIndexPlan

type RecordQueryAggregateIndexPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryAggregateIndexPlan wraps an index scan that reads from an aggregate index (e.g. SUM, COUNT) and reconstructs records from the index entries. This is a leaf plan (no children — the wrapped RecordQueryIndexPlan is a structural field, not a child in the plan tree sense). Mirrors Java's RecordQueryAggregateIndexPlan.

Fields:

  • indexPlan: the underlying index scan plan.

  • recordTypeName: the base record type name, used FOR A METADATA LOOKUP (cascades_generator.go derives this plan's result-column types by calling md.GetRecordType on it) as well as for the explain string and the scan-range execution identity.

    THAT LOOKUP IS NIL-TOLERANT AND ITS MISS IS SILENT, which is a live hazard rather than a nicety: on a miss the descriptor stays nil, every GROUP BY column falls back to STRING, and an aggregate OVER A COLUMN falls back to BIGINT -- plausible defaults, wrong types, no error. COUNT(*) is BIGINT with or without the miss, so it is the one output the miss does not degrade. A SECOND consumer defaults differently: the multi-intersection derivation reports GROUP BY columns as BIGINT, and it reaches its miss only when EVERY child plan misses -- so the degraded type depends on which derivation ran, which is worse than either default alone.

    RFC-238 §7f carries the two axes that could reach the miss, and BOTH ARE NOW CLOSED, for different reasons. The namespace one is forbidden by §7c's committed design, which translates on the QUERY side precisely so the candidate side does not move; it does not arm, and the reference is not licence to move it. The EMPTY association -- RecordTypesForIndex returning nothing for an index that is neither universal nor associated, leaving this field empty so GetRecordType("") misses -- is refused in Build, which requires every registered index to be universal or claimed by some record type. An earlier version of this paragraph said the state had exactly ONE route, a second SetRecords call; it had several, because the builder hands out live maps, and enumerating them is what went wrong. Pinned by TestBuildRefusesAnIndexNoRecordTypeClaims and TestBuiltMetadataIsDetachedFromTheBuilder in pkg/recordlayer.

    WHAT THAT ROUTE COST IS NOT WHAT THIS COMMENT ANALYSES, which is worth knowing before reviving the analysis above. An orphaned index did not merely lose its descriptor: ToProto emitted it with an EMPTY RecordType list, and a reload reads that as UNIVERSAL, so after a serialization round trip RecordTypesForIndex answered with EVERY type rather than none. The degraded-result-type hazard described here therefore did not survive a reload; a different defect did. It matters HERE because this field carries whichever namespace the plan was built in (RFC-238 §7c), so a plan built with a SQL spelling against metadata keyed by the stored one misses and degrades exactly that way.

  • resultType: the rich Type of the aggregated result row.

  • aggregateFunction: the name of the aggregate function (e.g. "SUM", "COUNT", "MIN", "MAX").

func NewRecordQueryAggregateIndexPlan

func NewRecordQueryAggregateIndexPlan(
	indexPlan *RecordQueryIndexPlan,
	recordTypeName string,
	resultType values.Type,
	aggregateFunction string,
) (*RecordQueryAggregateIndexPlan, error)

NewRecordQueryAggregateIndexPlan constructs an aggregate index plan.

func (*RecordQueryAggregateIndexPlan) CanonicalAggColumnName

func (p *RecordQueryAggregateIndexPlan) CanonicalAggColumnName() string

CanonicalAggColumnName returns the canonical column name the executor's aggregateIndexCursor writes the aggregate value under: "FUNC(*)" for an empty aggColumn (e.g. COUNT(*)), else "FUNC(col)". Single source of that name so the cursor and planColumnNamesWithMD stay byte-identical.

func (*RecordQueryAggregateIndexPlan) EqualsPlanWithoutChildren

func (p *RecordQueryAggregateIndexPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares index plan, record type name, and result type.

func (*RecordQueryAggregateIndexPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryAggregateIndexPlan) Explain

Explain renders AggregateIndex(function, indexName, [groupCols], recordType), with a trailing ", live_groups_only" when the scan drops zero-valued entries (RFC-209 §5.3(a)) — a property that changes the answer, so it is not allowed to be invisible in the plan.

func (*RecordQueryAggregateIndexPlan) GetAggColumn

func (p *RecordQueryAggregateIndexPlan) GetAggColumn() string

GetAggColumn returns the aggregate column name.

func (*RecordQueryAggregateIndexPlan) GetAggregateFunction

func (p *RecordQueryAggregateIndexPlan) GetAggregateFunction() string

GetAggregateFunction returns the aggregate function name.

func (*RecordQueryAggregateIndexPlan) GetChildren

GetChildren returns nil — this is a leaf plan. The wrapped index plan is a structural field, not a child (mirrors Java where RecordQueryAggregateIndexPlan implements RecordQueryPlanWithNoChildren).

func (*RecordQueryAggregateIndexPlan) GetGroupCols

func (p *RecordQueryAggregateIndexPlan) GetGroupCols() []string

GetGroupCols returns the grouping column names.

func (*RecordQueryAggregateIndexPlan) GetGroupColumnLayout

func (p *RecordQueryAggregateIndexPlan) GetGroupColumnLayout() values.Type

GetGroupColumnLayout returns the declared layout the grouping-column names resolve against, or nil when none was carried.

func (*RecordQueryAggregateIndexPlan) GetIndexName

func (p *RecordQueryAggregateIndexPlan) GetIndexName() string

GetIndexName returns the index name from the underlying plan.

func (*RecordQueryAggregateIndexPlan) GetIndexPlan

GetIndexPlan returns the underlying index plan.

func (*RecordQueryAggregateIndexPlan) GetKeyComponentTypes

func (p *RecordQueryAggregateIndexPlan) GetKeyComponentTypes() []values.Type

GetKeyComponentTypes returns the authoritative physical grouping-key types aligned with the underlying index scan's comparisons.

func (*RecordQueryAggregateIndexPlan) GetPhysicalGroupingPrefixCount

func (p *RecordQueryAggregateIndexPlan) GetPhysicalGroupingPrefixCount() int

GetPhysicalGroupingPrefixCount returns the g-p boundary before the inserted aggregate value in a permuted BY_GROUP key.

func (*RecordQueryAggregateIndexPlan) GetRecordQueryPlan

func (p *RecordQueryAggregateIndexPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryAggregateIndexPlan) GetRecordTypeName

func (p *RecordQueryAggregateIndexPlan) GetRecordTypeName() string

GetRecordTypeName returns the base record type name.

func (*RecordQueryAggregateIndexPlan) GetResultType

func (p *RecordQueryAggregateIndexPlan) GetResultType() values.Type

GetResultType returns the aggregate result type.

func (*RecordQueryAggregateIndexPlan) GetResultValue

func (p *RecordQueryAggregateIndexPlan) GetResultValue() values.Value

GetResultValue returns the aggregate-index plan's STABLE per-instance result value — the single correlation identity a bare aggregate-index plan carries as its own memo expression (RFC-184 W2). Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryAggregateIndexPlan) HashCodeWithoutChildren

func (p *RecordQueryAggregateIndexPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes index plan hash, record type, and aggregate function.

func (*RecordQueryAggregateIndexPlan) HintCost

HintCost: an aggregate index materializes one row per group.

func (*RecordQueryAggregateIndexPlan) HintOrdering

HintOrdering: an aggregate index is stored grouped, so it emits one row per group in group-column KEY order — which is the group's VALUE order only for coordinates whose tuple encoding is order-preserving under the comparator. The claim is therefore truncated at the first FLOAT/DOUBLE grouping column, by the same authority every other producer here asks: a negative-NaN group is the physically first row and the logically last one, and the NaN groups form one tie class split across two disjoint physical ranges, so no later grouping column is ordered within it either.

The grouping columns are NAMES, so answering this needs a layout — carried as groupColLayout from the match candidate's base record type. With none (a multi-record-type index), the predicate's fail-open direction applies and the claim stands, exactly as it does for an untyped index scan.

func (*RecordQueryAggregateIndexPlan) IsLiveGroupsOnly

func (p *RecordQueryAggregateIndexPlan) IsLiveGroupsOnly() bool

IsLiveGroupsOnly reports whether the scan drops zero-valued entries.

func (*RecordQueryAggregateIndexPlan) IsReverse

func (p *RecordQueryAggregateIndexPlan) IsReverse() bool

IsReverse delegates to the underlying index plan.

func (*RecordQueryAggregateIndexPlan) OutputColumnNames

func (p *RecordQueryAggregateIndexPlan) OutputColumnNames() []string

OutputColumnNames returns the column names this plan's rows are keyed by — the grouping columns (verbatim, as the cursor writes them) followed by the canonical aggregate name. A bare aggregate-index plan is always UNALIASED (an aliased SELECT tops with a Project that owns the rename), so there is no alias to carry; these are exactly the keys aggregateIndexCursor writes. Used by planColumnNamesWithMD so a UNION position-remap can normalize a grouped aggregate-index branch (RFC-081).

func (*RecordQueryAggregateIndexPlan) ProvenCardinalities

ProvenCardinalities: the group count an aggregate index materializes is data, not structure.

func (*RecordQueryAggregateIndexPlan) WithGroupColumnLayout

func (p *RecordQueryAggregateIndexPlan) WithGroupColumnLayout(layout values.Type) *RecordQueryAggregateIndexPlan

WithGroupColumnLayout carries the declared layout the grouping-column names resolve against — the base record type's descriptor-shaped positional type. Only HintOrdering reads it, to decide whether a grouping column may extend the group-order claim this plan makes.

func (*RecordQueryAggregateIndexPlan) WithGroupColumns

func (p *RecordQueryAggregateIndexPlan) WithGroupColumns(groupCols []string, aggColumn string) *RecordQueryAggregateIndexPlan

WithGroupColumns sets the grouping and aggregate column names for the executor to map index entries to result rows.

func (*RecordQueryAggregateIndexPlan) WithLiveGroupsOnly

WithLiveGroupsOnly marks this scan as dropping zero-valued entries — see the liveGroupsOnly field. Only a grouped COUNT(*) index may carry it. It COPIES, like every other WithXxx on a plan. Mutating in place would be mutating plan IDENTITY: liveGroupsOnly is folded into structuralKey precisely because a scan that drops vacated groups is a different plan from one that does not (see structuralKey below). An in-place write therefore changes the identity of an object the memo may already hold, and the memo would keep serving it under its former key.

That was latent rather than live only because every caller happens to invoke a COPYING builder first (WithGroupColumns), so the in-place write landed on a fresh copy. Reordering one chain would have armed it.

func (*RecordQueryAggregateIndexPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryComparatorPlan

type RecordQueryComparatorPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryComparatorPlan is a multi-child plan that executes all child plans and compares their results using a comparison key. Results from child plans are assumed to all be in a compatible sort order. Mirrors Java's RecordQueryComparatorPlan.

Fields:

  • children: the list of sub-plans whose results are compared.
  • comparisonKeyValues: values by which the results are compared (equivalent to Java's KeyExpression comparisonKey).
  • referencePlanIndex: the index of the "reference plan" (source of truth) among the sub-plans.
  • reverse: whether the children produce results in reverse order.
  • abortOnComparisonFailure: whether to abort execution when a comparison mismatch is detected (used in testing).

The children are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `children []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2. Child ORDER is doubly load-bearing here: referencePlanIndex indexes into it.

func NewRecordQueryComparatorPlan

func NewRecordQueryComparatorPlan(
	children []RecordQueryPlan,
	comparisonKeyValues []values.Value,
	referencePlanIndex int,
	reverse bool,
	abortOnComparisonFailure bool,
) (*RecordQueryComparatorPlan, error)

NewRecordQueryComparatorPlan constructs a comparator plan. Returns an error if children is empty, their exact types disagree, or referencePlanIndex is out of range.

func (*RecordQueryComparatorPlan) AbortOnComparisonFailure

func (p *RecordQueryComparatorPlan) AbortOnComparisonFailure() bool

AbortOnComparisonFailure reports whether mismatches abort execution.

func (*RecordQueryComparatorPlan) EqualsPlanWithoutChildren

func (p *RecordQueryComparatorPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryComparatorPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryComparatorPlan) Explain

func (p *RecordQueryComparatorPlan) Explain() string

Explain renders Comparator(child1, child2, ..., ref=N).

func (*RecordQueryComparatorPlan) GetChildren

func (p *RecordQueryComparatorPlan) GetChildren() []RecordQueryPlan

GetChildren returns the child plans, dereferenced through the quantifiers and in the order referencePlanIndex indexes into.

func (*RecordQueryComparatorPlan) GetComparisonKeyValues

func (p *RecordQueryComparatorPlan) GetComparisonKeyValues() []values.Value

GetComparisonKeyValues returns the comparison key values.

func (*RecordQueryComparatorPlan) GetQuantifiers

func (p *RecordQueryComparatorPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifiers, overriding PlanExprBase's none.

func (*RecordQueryComparatorPlan) GetRecordQueryPlan

func (p *RecordQueryComparatorPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryComparatorPlan) GetReferencePlanIndex

func (p *RecordQueryComparatorPlan) GetReferencePlanIndex() int

GetReferencePlanIndex returns the index of the reference plan.

func (*RecordQueryComparatorPlan) GetResultType

func (p *RecordQueryComparatorPlan) GetResultType() values.Type

GetResultType returns the type of the plan's result value. There is no childless case to answer for: the constructor rejects an empty child list.

func (*RecordQueryComparatorPlan) HashCodeWithoutChildren

func (p *RecordQueryComparatorPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes comparison keys (semantic Value hashes), reference index, and reverse flag.

func (*RecordQueryComparatorPlan) IsReverse

func (p *RecordQueryComparatorPlan) IsReverse() bool

IsReverse reports the scan direction.

func (*RecordQueryComparatorPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

The arity check is what keeps referencePlanIndex in range: it was validated against the child count at construction, so a same-length replacement cannot invalidate it.

type RecordQueryCoveringIndexPlan

type RecordQueryCoveringIndexPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryCoveringIndexPlan is an index scan that answers from the index entry alone — it reconstructs a PARTIAL record from the entry's covered columns instead of resolving the base record by primary key. Mirrors Java's `RecordQueryCoveringIndexPlan`.

The inner index plan is held as a plain FIELD, never as a quantifier and never as a child. That mirrors Java, where the type `implements RecordQueryPlanWithNoChildren` and the access path memoizes only the covering plan (ValueIndexScanMatchCandidate.tryFetchCoveringIndexScan), leaving the index plan a field on it. Two things depend on the inner staying invisible to child traversal:

  • Soundness of the memo. If the inner were a child quantifier, rules matching a bare index plan would yield a group member into the inner's Reference whose rows are FULL records, while this plan's rows are PARTIAL records. Those are not interchangeable, so they must not share a group.
  • Cost classification. The cost model's expression census counts an index scan it can reach; reaching the inner would restore `indexScanCount == 1` for a plan that performs no fetch, which `isSingularIndexScanWithFetch` reads as "a singular index scan WITH a fetch" — a contradiction that routes a fetchless covering scan to the contested cost tier.

Because the inner is a field, nothing in generic child traversal folds it into identity. structuralKey therefore folds the inner's FULL identity (via the inner's own structural key), not merely the covering columns: two covering scans over the same index with different scan ranges are different plans and must not collapse into one Reference.

func NewRecordQueryCoveringIndexPlan

func NewRecordQueryCoveringIndexPlan(indexPlan *RecordQueryIndexPlan) (*RecordQueryCoveringIndexPlan, error)

NewRecordQueryCoveringIndexPlan wraps an index scan as a covering scan. Mirrors Java's construction at the access path, which is unconditional whenever the entry can be turned into a partial record and never consults the projection.

The covered columns are DERIVED from the inner scan rather than accepted from the caller. Accepting them made an inconsistent pair representable — a column list naming something the entry does not carry, or omitting something it does — and the executor aligns that list POSITIONALLY against (index key values ++ entry value tuple). A mismatch there is not a loud failure; it silently reads a value into the wrong logical slot. Deriving removes the failure mode instead of documenting it.

func (*RecordQueryCoveringIndexPlan) EqualsPlanWithoutChildren

func (p *RecordQueryCoveringIndexPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryCoveringIndexPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryCoveringIndexPlan) Explain

func (p *RecordQueryCoveringIndexPlan) Explain() string

Explain renders the inner scan's label carrying the COVERING marker, so a covering scan reads as `IndexScan(IDX, [=] COVERING)`. Java renders its covering plan as `COVERING(IDX [...] -> ...)`; converging on that shape is deliberately out of scope here and would churn every plan golden for an unrelated reason.

The marker is passed DOWN to the inner's label builder rather than spliced into the finished string. A splice at the last "]" cannot tell "the marker is absent" from "the marker is already there", so it double-stamps (`[] COVERING COVERING`), and it silently relocates if the label's bracket ever moves.

func (*RecordQueryCoveringIndexPlan) GetChildren

func (p *RecordQueryCoveringIndexPlan) GetChildren() []RecordQueryPlan

GetChildren returns nil. The inner index plan is a field, not a child — see the type comment for why that is load-bearing rather than incidental.

func (*RecordQueryCoveringIndexPlan) GetColumnNames

func (p *RecordQueryCoveringIndexPlan) GetColumnNames() []string

GetColumnNames delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetCommonPrimaryKeyValues

func (p *RecordQueryCoveringIndexPlan) GetCommonPrimaryKeyValues() []values.Value

GetCommonPrimaryKeyValues delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryCoveringIndexPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren reports the correlations reached through the inner scan's comparison operands. The inner is not a child, so its correlations would otherwise be invisible to correlation analysis — which would let a rule hoist this plan above the quantifier its range depends on.

func (*RecordQueryCoveringIndexPlan) GetCoveringColumns

func (p *RecordQueryCoveringIndexPlan) GetCoveringColumns() []string

GetCoveringColumns returns the entry-layout column names this scan covers.

func (*RecordQueryCoveringIndexPlan) GetDistinctProofIndexName

func (p *RecordQueryCoveringIndexPlan) GetDistinctProofIndexName() string

GetDistinctProofIndexName implements DistinctProofStamped by delegating to the inner scan, which is where the stamp is carried.

func (*RecordQueryCoveringIndexPlan) GetFlowedType

func (p *RecordQueryCoveringIndexPlan) GetFlowedType() values.Type

GetFlowedType delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetIndexName

func (p *RecordQueryCoveringIndexPlan) GetIndexName() string

GetIndexName delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetIndexPlan

GetIndexPlan returns the wrapped index scan. It is a field, not a child: callers that walk the plan tree will NOT reach it, by design.

Nil-tolerant on the receiver, via inner(): this is IndexScanCarrier's single method, and the hint-contract parity harnesses enumerate plan types as TYPED NILS. A carrier accessor that panics on the enumeration shape would make the interface unusable exactly where it is most useful — a generic walk that does not know which concrete type it holds.

func (*RecordQueryCoveringIndexPlan) GetKeyComponentTypes

func (p *RecordQueryCoveringIndexPlan) GetKeyComponentTypes() []values.Type

GetKeyComponentTypes delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetPKColumnNames

func (p *RecordQueryCoveringIndexPlan) GetPKColumnNames() []string

GetPKColumnNames delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetPrimaryKeyComponentTypes

func (p *RecordQueryCoveringIndexPlan) GetPrimaryKeyComponentTypes() []values.Type

GetPrimaryKeyComponentTypes delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetRecordQueryPlan

func (p *RecordQueryCoveringIndexPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryCoveringIndexPlan) GetRecordTypes

func (p *RecordQueryCoveringIndexPlan) GetRecordTypes() []string

GetRecordTypes delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) GetResultType

func (p *RecordQueryCoveringIndexPlan) GetResultType() values.Type

GetResultType returns the inner scan's flowed row Type. Java's covering plan likewise reports the base record's type rather than a projected/flattened shape.

func (*RecordQueryCoveringIndexPlan) GetResultValue

func (p *RecordQueryCoveringIndexPlan) GetResultValue() values.Value

GetResultValue returns the STABLE per-instance result value minted by the constructor — the only way this type is built.

func (*RecordQueryCoveringIndexPlan) GetScanComparisons

func (p *RecordQueryCoveringIndexPlan) GetScanComparisons() []*predicates.ComparisonRange

GetScanComparisons delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) HashCodeWithoutChildren

func (p *RecordQueryCoveringIndexPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryCoveringIndexPlan) HintCost

HintCost delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) HintOrdering

HintOrdering delegates to the inner scan. Without this the covering scan would derive NO ordering, RemoveSortRule could not fire above it, and every order-satisfying index access would sprout an in-memory sort.

func (*RecordQueryCoveringIndexPlan) HintRichOrdering

func (p *RecordQueryCoveringIndexPlan) HintRichOrdering() *properties.RichOrdering

HintRichOrdering delegates to the inner scan, for the same reason as HintOrdering — and additionally because the rich form is what carries the equality-prefix bindings a sort-elimination match needs.

func (*RecordQueryCoveringIndexPlan) IsReverse

func (p *RecordQueryCoveringIndexPlan) IsReverse() bool

IsReverse delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) IsStrictlySorted

func (p *RecordQueryCoveringIndexPlan) IsStrictlySorted() bool

IsStrictlySorted delegates to the inner scan, mirroring Java's RecordQueryCoveringIndexPlan.isStrictlySorted (RecordQueryCoveringIndexPlan.java:174-176). Reconstructing a partial record from an entry cannot break a strict ordering the entry stream already has.

func (*RecordQueryCoveringIndexPlan) IsUnique

func (p *RecordQueryCoveringIndexPlan) IsUnique() bool

IsUnique delegates to the inner scan: uniqueness is a property of the INDEX, and a covering scan reads the same index.

func (*RecordQueryCoveringIndexPlan) ProducesDistinctRecords

func (p *RecordQueryCoveringIndexPlan) ProducesDistinctRecords() bool

ProducesDistinctRecords delegates to the inner scan: reconstructing a partial record from an entry neither creates nor removes duplicates.

func (*RecordQueryCoveringIndexPlan) ProvenCardinalities

ProvenCardinalities delegates to the inner scan.

func (*RecordQueryCoveringIndexPlan) WithDistinctProofIndexName

func (p *RecordQueryCoveringIndexPlan) WithDistinctProofIndexName(indexName string) RecordQueryPlan

WithDistinctProofIndexName implements DistinctProofStampable, stamping the inner scan and returning a copy over it.

func (*RecordQueryCoveringIndexPlan) WithIndexPlan

WithIndexPlan returns a shallow copy over a rewritten inner scan, preserving the stable result value. Used by rewrites that rebase the inner's scan comparisons.

The covered columns are RE-DERIVED from the new inner rather than carried over: carrying them would let a rewrite that changes the inner's covered surface leave this plan describing the old one, which the executor would then align positionally against the new entry layout.

func (*RecordQueryCoveringIndexPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers. The inner index plan is a field and is deliberately not exposed as one.

type RecordQueryDefaultOnEmptyPlan

type RecordQueryDefaultOnEmptyPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryDefaultOnEmptyPlan returns the inner plan's rows if any exist, or a single row with the default value if the inner is empty. Mirrors Java's RecordQueryDefaultOnEmptyPlan.

func NewRecordQueryDefaultOnEmptyPlan

func NewRecordQueryDefaultOnEmptyPlan(inner RecordQueryPlan, defaultValue values.Value) (*RecordQueryDefaultOnEmptyPlan, error)

func NewRecordQueryDefaultOnEmptyPlanFromQuantifier

func NewRecordQueryDefaultOnEmptyPlanFromQuantifier(innerQ expressions.Quantifier, defaultValue values.Value) (*RecordQueryDefaultOnEmptyPlan, error)

NewRecordQueryDefaultOnEmptyPlanFromQuantifier builds a default-on-empty whose child is a LIVE memo quantifier (the implementation rule passes the live currentQuant) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / GetResultValue all resolve through the one live edge (RFC-184 W2).

func (*RecordQueryDefaultOnEmptyPlan) EqualsPlanWithoutChildren

func (p *RecordQueryDefaultOnEmptyPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryDefaultOnEmptyPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryDefaultOnEmptyPlan) Explain

func (*RecordQueryDefaultOnEmptyPlan) GetChildren

func (*RecordQueryDefaultOnEmptyPlan) GetDefaultValue

func (p *RecordQueryDefaultOnEmptyPlan) GetDefaultValue() values.Value

func (*RecordQueryDefaultOnEmptyPlan) GetInner

func (*RecordQueryDefaultOnEmptyPlan) GetInnerQuantifier

func (p *RecordQueryDefaultOnEmptyPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the default-on-empty ranges over. derivationsForDefaultOnEmpty reads its alias to translate the default value's correlation; since RFC-184 W2 the memo holds the bare plan (no physicalDefaultOnEmptyWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryDefaultOnEmptyPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryDefaultOnEmptyPlan) GetRecordQueryPlan

func (p *RecordQueryDefaultOnEmptyPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryDefaultOnEmptyPlan) GetResultType

func (p *RecordQueryDefaultOnEmptyPlan) GetResultType() values.Type

func (*RecordQueryDefaultOnEmptyPlan) GetResultValue

func (p *RecordQueryDefaultOnEmptyPlan) GetResultValue() values.Value

GetResultValue returns the stable exact carrier admitted from both result alternatives. It is nullable when either the child or default is nullable, matching Java's DerivedValue(child, default) result contract.

func (*RecordQueryDefaultOnEmptyPlan) HashCodeWithoutChildren

func (p *RecordQueryDefaultOnEmptyPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryDefaultOnEmptyPlan) HintCost

HintCost: DefaultOnEmpty passes its child through unchanged — literally, Cardinality AND CPU. It is a per-row null-extension shim over the SAME rows the child produces, not an alternative implementation competing in the memo, so it earns no physical-wrapper CPU discount of its own — unlike every other wrapper here, it adds no real execution step worth pricing.

func (*RecordQueryDefaultOnEmptyPlan) HintOrdering

HintOrdering: passing the child through preserves its order.

func (*RecordQueryDefaultOnEmptyPlan) OrderingSourceRef

func (p *RecordQueryDefaultOnEmptyPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryDefaultOnEmptyPlan) ProvenCardinalities

ProvenCardinalities: DefaultOnEmpty guarantees at least one row — real-or-default — so the child's bounds are floored at one.

func (*RecordQueryDefaultOnEmptyPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the default-on-empty carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the default value, and GetInner re-resolves through the new singleton reference. This replaces physicalDefaultOnEmptyWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild gated on isLeafReplaceable — a single live child edge needs neither.

func (*RecordQueryDefaultOnEmptyPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryDeletePlan

type RecordQueryDeletePlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryDeletePlan is the physical DELETE plan: deletes records emitted by an inner plan. Mirrors a simplified subset of Java's `RecordQueryDeletePlan`.

Java's full surface includes pre-delete + post-delete hooks, versionstamp generation, plan-graph rewriting. The seed ports the minimal node-information needed by ImplementDeleteRule:

  • inner: the source plan emitting rows to delete (typically a filter/scan that selects the target rows)
  • targetRecordType: the destination record type name

func NewRecordQueryDeletePlan

func NewRecordQueryDeletePlan(inner RecordQueryPlan, targetRecordType string) (*RecordQueryDeletePlan, error)

NewRecordQueryDeletePlan constructs the DELETE plan.

func NewRecordQueryDeletePlanFromQuantifier

func NewRecordQueryDeletePlanFromQuantifier(innerQ expressions.Quantifier, targetRecordType string) (*RecordQueryDeletePlan, error)

NewRecordQueryDeletePlanFromQuantifier builds a DELETE whose child is a LIVE memo quantifier (the implementation rule passes ForEachQuantifier(MemoizeExpression(winner))) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / GetResultValue all resolve through the one live edge (RFC-184 W2).

func (*RecordQueryDeletePlan) EqualsPlanWithoutChildren

func (p *RecordQueryDeletePlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryDeletePlan) EqualsWithoutChildren

func (p *RecordQueryDeletePlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryDeletePlan) Explain

func (p *RecordQueryDeletePlan) Explain() string

Explain renders Delete(target, inner).

func (*RecordQueryDeletePlan) GetChildren

func (p *RecordQueryDeletePlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryDeletePlan) GetInner

func (p *RecordQueryDeletePlan) GetInner() RecordQueryPlan

GetInner returns the source plan, dereferenced through the quantifier.

func (*RecordQueryDeletePlan) GetQuantifiers

func (p *RecordQueryDeletePlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryDeletePlan) GetRecordQueryPlan

func (p *RecordQueryDeletePlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryDeletePlan) GetResultType

func (p *RecordQueryDeletePlan) GetResultType() values.Type

GetResultType returns the inner's result type.

func (*RecordQueryDeletePlan) GetResultValue

func (p *RecordQueryDeletePlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the live child quantifier — DELETE passes its inner's rows through, so the result identity is the inner's, the value physicalDeleteWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryDeletePlan) GetTargetRecordType

func (p *RecordQueryDeletePlan) GetTargetRecordType() string

GetTargetRecordType returns the destination record-type name.

func (*RecordQueryDeletePlan) HashCodeWithoutChildren

func (p *RecordQueryDeletePlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes class + targetRecordType.

func (*RecordQueryDeletePlan) HintCost

HintCost: one write per consumed row.

func (*RecordQueryDeletePlan) ProvenCardinalities

func (p *RecordQueryDeletePlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: one effect per consumed row.

func (*RecordQueryDeletePlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the plan carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the target, and GetInner re-resolves through the new singleton reference. This replaces physicalDeleteWrapper.WithChildren (RFC-184 W2).

func (*RecordQueryDeletePlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryDistinctPlan

type RecordQueryDistinctPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryDistinctPlan removes duplicate rows from an inner plan's row stream. Mirrors Java's `RecordQueryUnorderedPrimaryKeyDistinctPlan` (the simpler unordered-distinct shape — Java has multiple distinct-plan flavors: ordered / unordered / by-key / by-row). The seed picks unordered-by-row.

Result type matches inner — distinct doesn't reshape rows. The child is stored ONCE, as a Quantifier over a Reference — Java's shape (`private final Quantifier.Physical inner`, dereferenced by getChild()). The raw `inner RecordQueryPlan` pointer it replaces was the second storage location for the same edge; a nil-inner "shell" was precisely the state where that pointer and the wrapper's quantifier disagreed. With one location there is nothing to disagree with. RFC-183 P5 step 2.

func NewRecordQueryDistinctPlan

func NewRecordQueryDistinctPlan(inner RecordQueryPlan) (*RecordQueryDistinctPlan, error)

NewRecordQueryDistinctPlan constructs a distinct plan over the given inner plan.

func NewRecordQueryDistinctPlanFromQuantifier

func NewRecordQueryDistinctPlanFromQuantifier(innerQ expressions.Quantifier, streaming bool) (*RecordQueryDistinctPlan, error)

NewRecordQueryDistinctPlanFromQuantifier builds a distinct whose child is a supplied memo quantifier instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly — the memo holds it without a physicalDistinctWrapper (RFC-184 W2).

The streaming flag is passed EXPLICITLY because it is the ordering-critical axis: it is sound only when the inner is ordered by the dedup key (equal rows adjacent), so it MUST be computed against the exact inner this quantifier resolves to. Unlike a plain (hash) distinct — which dedups over any inner and therefore carries the LIVE shared-group edge, following push-rule canonicalization — a STREAMING distinct freezes its ordering-critical inner in a DETACHED single-member final reference so planFromQuantifier resolves that exact member and the streaming executor never runs over an unordered float. See newPhysicalDistinctFor.

func NewRecordQueryStreamingDistinctPlan

func NewRecordQueryStreamingDistinctPlan(inner RecordQueryPlan) (*RecordQueryDistinctPlan, error)

NewRecordQueryStreamingDistinctPlan is NewRecordQueryDistinctPlan with the ordering-critical streaming flag set.

It exists so the flag can be chosen at CONSTRUCTION and nowhere else. It used to be an exported field, which made it settable on a finished plan from any package — and it is the FIRST component of this plan's structuralKey, so such a write rewrites the identity of a plan the memo may already hold, under an unchanged pointer that the memo's owner check cannot distinguish from the original.

There is deliberately no WithStreaming builder. A copying builder would be safe for the memo but wrong for this field: streaming is sound only when the inner is ordered by the dedup key, so it must be DERIVED from the inner rather than applied to a plan afterwards. Making construction the only entry point keeps that derivation and the flag in one place.

func (*RecordQueryDistinctPlan) EqualsPlanWithoutChildren

func (p *RecordQueryDistinctPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryDistinctPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryDistinctPlan) Explain

func (p *RecordQueryDistinctPlan) Explain() string

Explain renders Distinct(inner), plus the R3 narrowing when present.

The Streaming mode is an execution-only detail (resume-clean adjacent-dedup vs fresh-per-page hash-set) that produces identical rows, so it is deliberately NOT surfaced here — keeping plan-shape assertions stable. The fix it enables is proved by row-level cross-page tests, not EXPLAIN.

The NARROWING is rendered, and the difference from Streaming is the reason. Streaming picks between two executors that retain the same keys; narrowing changes WHICH ROWS THE OPERATOR RETAINS. That is the optimization itself, and an acceptance criterion has to be able to assert it fired — a narrowed distinct that silently degraded to a full one is otherwise indistinguishable from one that never narrowed. Naming the licensing index makes it a positive assertion rather than an absence, for the same reason the elision's own stamp is rendered.

func (*RecordQueryDistinctPlan) GetChildren

func (p *RecordQueryDistinctPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryDistinctPlan) GetDistinctProofIndexName

func (p *RecordQueryDistinctPlan) GetDistinctProofIndexName() string

GetDistinctProofIndexName implements DistinctProofStamped. On a distinct plan the stamp does not mean "an operator was elided above this node" — it means "this operator's dedup was NARROWED on the strength of that index". Both are dependencies of the same kind and for the same reason, so the dependency walk asks one capability and gets both.

func (*RecordQueryDistinctPlan) GetInner

GetInner returns the inner plan, dereferenced through the quantifier.

func (*RecordQueryDistinctPlan) GetInnerQuantifier

func (p *RecordQueryDistinctPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the distinct ranges over. The push rules read it to reach the distinct's inner group; since RFC-184 W2 the memo holds the bare plan (no physicalDistinctWrapper whose innerQuant field they used to read), this exposes the same edge.

func (*RecordQueryDistinctPlan) GetNarrowedExemptSlots

func (p *RecordQueryDistinctPlan) GetNarrowedExemptSlots() []int

GetNarrowedExemptSlots returns the dedup-key slot positions the residual dedup tests, or nil for "every slot".

func (*RecordQueryDistinctPlan) GetQuantifiers

func (p *RecordQueryDistinctPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryDistinctPlan) GetRecordQueryPlan

func (p *RecordQueryDistinctPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryDistinctPlan) GetResultType

func (p *RecordQueryDistinctPlan) GetResultType() values.Type

GetResultType returns the inner's result type.

func (*RecordQueryDistinctPlan) GetResultValue

func (p *RecordQueryDistinctPlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the child quantifier — a distinct drops duplicate rows but reshapes nothing, so its row identity IS the inner's. This is the identity physicalDistinctWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryDistinctPlan) HashCodeWithoutChildren

func (p *RecordQueryDistinctPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren discriminates on type and the Streaming mode.

func (*RecordQueryDistinctPlan) HintCost

HintCost: duplicate elimination over the child stream.

func (*RecordQueryDistinctPlan) HintOrdering

func (p *RecordQueryDistinctPlan) HintOrdering() properties.Ordering

HintOrdering: duplicate elimination drops repeats without reordering the survivors.

func (*RecordQueryDistinctPlan) IsNarrowedDedup

func (p *RecordQueryDistinctPlan) IsNarrowedDedup() bool

IsNarrowedDedup reports whether this distinct dedups only the exempt subset.

func (*RecordQueryDistinctPlan) IsStreaming

func (p *RecordQueryDistinctPlan) IsStreaming() bool

IsStreaming reports whether this distinct uses the adjacent-dedup executor. See the field doc for the ordering precondition that makes it sound.

func (*RecordQueryDistinctPlan) OrderingSourceRef

func (p *RecordQueryDistinctPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryDistinctPlan) ProvenCardinalities

ProvenCardinalities: full-row duplicate elimination — the current model conservatively preserves the child's bounds rather than claiming a dedup ratio it cannot prove.

func (*RecordQueryDistinctPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The distinct carries its child as a single memo edge, so the relink is a quantifier swap: WithQuantifiers copies the receiver (preserving the Streaming mode — the flag a constructor rebuild would reset and thereby downgrade a resume-clean streaming distinct to the memory-heavy hash-set, TODO C5: cross-page correctness was fixed 2026-07-20 — the hash-set is no longer wrong across pages; streaming is preferred for O(1) memory) and re-resolves GetInner through the new singleton reference. This replaces physicalDistinctWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a WithInner rebuild gated on isLeafReplaceable — a gate that DECLINED to relink onto a non-leaf-replaceable (e.g. projection) pinned inner and so kept a redundant enforcer sort Java's RemoveSortRule elides. The unconditional swap re-resolves through GetInner, reaches the executable plan, and lets that elision fire — a parity gain, the same as the predicates-filter collapse.

func (*RecordQueryDistinctPlan) WithInner

WithInner returns a copy with the inner replaced and every other field preserved — the extraction-relink rebuild path (see findPhysicalPlan's shell completion). A constructor rebuild would drop fields the setters carry, so identity-preserving copy is the only safe form.

func (*RecordQueryDistinctPlan) WithNarrowedDedup

func (p *RecordQueryDistinctPlan) WithNarrowedDedup(indexName string, exemptSlots []int) *RecordQueryDistinctPlan

WithNarrowedDedup returns a copy whose dedup is RESIDUAL: only rows carrying an exempt key component — NULL or NaN — enter the seen-set, and every other row passes through in O(1) with nothing retained.

This is R3, the route taken when neither the metadata proof nor a NULL-rejecting predicate establishes that the index's exempt set is empty. The soundness argument is one line: the index's uniqueness already guarantees at most one row per non-exempt key value, so a non-exempt row can duplicate neither another non-exempt row (uniqueness) nor an exempt one (exemptness is a property of the key value itself, so their keys differ by construction).

It STRICTLY DOMINATES the full operator, which is why it needs no cost-model trade-off and no cost formula moves: the narrowed seen-set is a SUBSET of the full one on every input — identical in the worst case where every row is exempt, and EMPTY on the ordinary case of a nullable column holding no NULLs, where the operator degenerates to a pass-through retaining nothing.

exemptSlots are positions in the DEDUP KEY's slot order (what distinctKey packs) holding the proving index's key components. A nil slice means "test every slot", which is the conservative form: it over-approximates the exempt set, so it is still a subset of the full seen-set and still sound, just less narrow. That is the fail-safe direction — the alternative, guessing a position, would under-approximate and drop rows.

indexName is the proving index, and it is recorded for the SAME reason a full elision records it. R3 reads as unconditional because it removes no operator, and that reading is wrong: R3 rests on the index's uniqueness exactly as R1 and R2 do. Withdraw the uniqueness guarantee and a non-exempt row can duplicate another non-exempt row — which is precisely what the narrowed seen-set no longer catches. So the plan carries the stamp, the dependency walk collects it through DistinctProofStamped, and the execution-time revalidation 40001s a statement whose proving index left READABLE. The STREAMING executor is REFUSED the narrowing, and the refusal lives here rather than at the call site because a plan that carries the flag and an executor that ignores it is the worst of the three possible states: EXPLAIN renders `narrowed-by`, an acceptance criterion reads it as fired, and the executor took the streaming branch and dedupped every row exactly as before.

Refusing costs nothing. The streaming executor retains ONE key — the previous row's — so there is no seen-set for a narrowing to shrink; the whole benefit is on the hash path, whose set the narrowing empties. And no dependency is lost by not stamping: streaming is only chosen when the inner is ordered by the dedup key, which on these shapes is a scan of the proving index itself, so the plan already names the index and the dependency walk already finds it. That is the same SOLE-LICENSE reasoning the elision arm applies — a stamp records a dependency the plan's correctness rests on and nothing else.

func (*RecordQueryDistinctPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference). The receiver is never mutated, which is what keeps a memoized plan safe to share.

type RecordQueryExplodePlan

type RecordQueryExplodePlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryExplodePlan "explodes" a collection-typed Value into a stream of element values. Leaf plan (no children). Mirrors Java's RecordQueryExplodePlan.

func NewRecordQueryExplodePlan

func NewRecordQueryExplodePlan(collectionValue values.Value) (*RecordQueryExplodePlan, error)

NewRecordQueryExplodePlan builds a bare (non-ordinal) Explode plan.

func NewRecordQueryExplodePlanWithOrdinality

func NewRecordQueryExplodePlanWithOrdinality(collectionValue values.Value, withOrdinality bool) (*RecordQueryExplodePlan, error)

NewRecordQueryExplodePlanWithOrdinality builds an Explode plan that also emits a 1-based ordinal alongside each element.

func (*RecordQueryExplodePlan) EqualsPlanWithoutChildren

func (p *RecordQueryExplodePlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryExplodePlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryExplodePlan) Explain

func (p *RecordQueryExplodePlan) Explain() string

func (*RecordQueryExplodePlan) GetChildren

func (p *RecordQueryExplodePlan) GetChildren() []RecordQueryPlan

func (*RecordQueryExplodePlan) GetCollectionValue

func (p *RecordQueryExplodePlan) GetCollectionValue() values.Value

func (*RecordQueryExplodePlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryExplodePlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren reports the correlations of this plan's collection value, mirroring physicalExplodeWrapper.

func (*RecordQueryExplodePlan) GetElementType

func (p *RecordQueryExplodePlan) GetElementType() values.Type

GetElementType returns the array element type, or UnknownType when the collection is not array-typed.

func (*RecordQueryExplodePlan) GetRecordQueryPlan

func (p *RecordQueryExplodePlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryExplodePlan) GetResultType

func (p *RecordQueryExplodePlan) GetResultType() values.Type

func (*RecordQueryExplodePlan) GetResultValue

func (p *RecordQueryExplodePlan) GetResultValue() values.Value

GetResultValue returns the explode's STABLE per-instance result value — the single correlation identity a bare explode carries as its own memo expression (RFC-184 W2). Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryExplodePlan) HashCodeWithoutChildren

func (p *RecordQueryExplodePlan) HashCodeWithoutChildren() uint64

func (*RecordQueryExplodePlan) HintCost

HintCost: exploding a literal collection yields one row per element; a non-literal collection falls back to a small default.

func (*RecordQueryExplodePlan) HintOrdering

func (p *RecordQueryExplodePlan) HintOrdering() properties.Ordering

HintOrdering: exploding a collection yields elements in no modeled order.

func (*RecordQueryExplodePlan) IsWithOrdinality

func (p *RecordQueryExplodePlan) IsWithOrdinality() bool

IsWithOrdinality reports whether the plan emits 1-based ordinals.

func (*RecordQueryExplodePlan) ProvenCardinalities

ProvenCardinalities: the exploded collection's length is a runtime value.

func (*RecordQueryExplodePlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryFetchFromPartialRecordPlan

type RecordQueryFetchFromPartialRecordPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryFetchFromPartialRecordPlan transforms a stream of partial records (index entries from a covering index scan) into full records by fetching via primary key. Mirrors Java's `RecordQueryFetchFromPartialRecordPlan`.

The plan has:

  • An inner plan that produces index entries (partial records).
  • A TranslateValueFunction that maps values from the full-record domain to the partial-record (index) domain — used by push-through rules to determine which predicates/values can be evaluated before the fetch.
  • A result type (the full record type post-fetch).
  • A FetchIndexRecords mode.

func NewRecordQueryFetchFromPartialRecordPlan

func NewRecordQueryFetchFromPartialRecordPlan(
	inner RecordQueryPlan,
	translateValueFunction TranslateValueFunction,
	resultType values.Type,
	fetchIndexRecords FetchIndexRecords,
) (*RecordQueryFetchFromPartialRecordPlan, error)

NewRecordQueryFetchFromPartialRecordPlan constructs the plan.

func NewRecordQueryFetchFromPartialRecordPlanFromQuantifier

func NewRecordQueryFetchFromPartialRecordPlanFromQuantifier(
	innerQ expressions.Quantifier,
	translateValueFunction TranslateValueFunction,
	resultType values.Type,
	fetchIndexRecords FetchIndexRecords,
) (*RecordQueryFetchFromPartialRecordPlan, error)

NewRecordQueryFetchFromPartialRecordPlanFromQuantifier builds a fetch whose child is a LIVE memo quantifier.

func (*RecordQueryFetchFromPartialRecordPlan) EqualsPlanWithoutChildren

func (p *RecordQueryFetchFromPartialRecordPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryFetchFromPartialRecordPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryFetchFromPartialRecordPlan) Explain

Explain renders Fetch(inner).

func (*RecordQueryFetchFromPartialRecordPlan) GetChildren

GetChildren returns the inner plan.

func (*RecordQueryFetchFromPartialRecordPlan) GetFetchIndexRecords

func (p *RecordQueryFetchFromPartialRecordPlan) GetFetchIndexRecords() FetchIndexRecords

GetFetchIndexRecords returns the fetch mode.

func (*RecordQueryFetchFromPartialRecordPlan) GetInner

GetInner returns the inner plan (typically a covering index scan), dereferenced through the quantifier.

func (*RecordQueryFetchFromPartialRecordPlan) GetInnerQuantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the fetch ranges over. Push/data-access rules that match a physical fetch in the memo need its inner GROUP (GetRangesOver) and alias to re-plan around it; since RFC-184 W2 the memo holds the bare plan (no physicalFetchFromPartialRecordWrapper whose innerQuant field they used to read), this exposes the same edge.

func (*RecordQueryFetchFromPartialRecordPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryFetchFromPartialRecordPlan) GetRecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryFetchFromPartialRecordPlan) GetResultType

GetResultType returns the full record type post-fetch.

func (*RecordQueryFetchFromPartialRecordPlan) GetTranslateValueFunction

func (p *RecordQueryFetchFromPartialRecordPlan) GetTranslateValueFunction() TranslateValueFunction

GetTranslateValueFunction returns the push-value function.

func (*RecordQueryFetchFromPartialRecordPlan) HashCodeWithoutChildren

func (p *RecordQueryFetchFromPartialRecordPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryFetchFromPartialRecordPlan) HintCost

HintCost: primary-key fetch of the full record per index entry.

func (*RecordQueryFetchFromPartialRecordPlan) HintOrdering

HintOrdering: fetching the full record per index entry preserves the index scan's order.

func (*RecordQueryFetchFromPartialRecordPlan) HintRichOrdering

HintRichOrdering: fetching the full record per index entry preserves the index scan's rich ordering, so inherit it from the source.

This DUPLICATES the physical wrapper's body rather than delegating to it, for the reason this file's header gives: same loop, but the wrapper walks a shared memo group while the plan walks the fresh singleton its own child quantifier ranges over. Two questions, two answers.

func (*RecordQueryFetchFromPartialRecordPlan) IsReverse

IsReverse delegates to the inner plan's reverse flag. Mirrors Java's RecordQueryFetchFromPartialRecordPlan.isReverse() which returns getChild().isReverse().

func (*RecordQueryFetchFromPartialRecordPlan) OrderingSourceRef

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryFetchFromPartialRecordPlan) ProvenCardinalities

ProvenCardinalities: a fetch is 1:1 — Java's CardinalitiesProperty passes it through, so a bounded index access under a Fetch keeps its proven max.

func (*RecordQueryFetchFromPartialRecordPlan) PushValue

PushValue attempts to translate a value from the full-record domain (correlated to sourceAlias) to the partial-record domain (correlated to targetAlias). Returns the translated value and true on success, or nil and false if translation is not possible.

Mirrors Java's `RecordQueryFetchFromPartialRecordPlan.pushValue`.

func (*RecordQueryFetchFromPartialRecordPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the fetch carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the translate function, result type and fetch mode, and GetInner re-resolves through the new singleton reference. This replaces physicalFetchFromPartialRecordWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild — a single live child edge needs none.

func (*RecordQueryFetchFromPartialRecordPlan) WithInner

WithInner returns a copy with the inner replaced and every other field preserved — the extraction-relink rebuild path (see findPhysicalPlan's shell completion). A constructor rebuild would drop fields the setters carry, so identity-preserving copy is the only safe form.

func (*RecordQueryFetchFromPartialRecordPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryFilterPlan

type RecordQueryFilterPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryFilterPlan applies a list of QueryPredicates to an inner plan's row stream. Mirrors Java's `RecordQueryFilterPlan`.

Seed surface: predicates list + inner plan. The plan's result type is the inner's result type (filter doesn't reshape rows).

Note: physical filter (the row-by-row ANDed predicate evaluation) vs logical filter (the LogicalFilterExpression rule input) are separate concepts. ImplementFilterRule (B5 Batch A) lifts a LogicalFilter into this plan.

func NewRecordQueryFilterPlan

func NewRecordQueryFilterPlan(preds []predicates.QueryPredicate, inner RecordQueryPlan) (*RecordQueryFilterPlan, error)

NewRecordQueryFilterPlan constructs a filter over the given predicates and inner plan.

func NewRecordQueryFilterPlanFromQuantifier

func NewRecordQueryFilterPlanFromQuantifier(preds []predicates.QueryPredicate, innerQ expressions.Quantifier) (*RecordQueryFilterPlan, error)

func (*RecordQueryFilterPlan) EqualsPlanWithoutChildren

func (p *RecordQueryFilterPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsPlanWithoutChildren compares the predicate list pairwise via PredicateEquals.

func (*RecordQueryFilterPlan) EqualsWithoutChildren

func (p *RecordQueryFilterPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryFilterPlan) Explain

func (p *RecordQueryFilterPlan) Explain() string

Explain renders Filter([P1, P2], inner).

func (*RecordQueryFilterPlan) GetChildren

func (p *RecordQueryFilterPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryFilterPlan) GetInner

func (p *RecordQueryFilterPlan) GetInner() RecordQueryPlan

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryFilterPlan) GetPredicates

func (p *RecordQueryFilterPlan) GetPredicates() []predicates.QueryPredicate

GetPredicates returns the predicate list (read-only).

func (*RecordQueryFilterPlan) GetQuantifiers

func (p *RecordQueryFilterPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryFilterPlan) GetRecordQueryPlan

func (p *RecordQueryFilterPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryFilterPlan) GetResultType

func (p *RecordQueryFilterPlan) GetResultType() values.Type

GetResultType returns the inner's result type (filter doesn't reshape rows).

func (*RecordQueryFilterPlan) HashCodeWithoutChildren

func (p *RecordQueryFilterPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes the class discriminator + per-predicate predicates.SemanticHashCode (alias-invariant, coarser than the structural PredicateEquals — equal⟹same-hash holds by construction). NOT Explain() display text: renderings are for humans, carry no identity contract, and drift independently of equality.

func (*RecordQueryFilterPlan) HintCost

HintCost: one selectivity factor per predicate. Counted via CountConjuncts, NOT len(), so this agrees with RecordQueryPredicatesFilterPlan.HintCost and NestedLoopJoinCost on the SAME logical residual regardless of whether the constructing rule packaged N conditions as one AndPredicate or N top-level list entries — see predicates.CountConjuncts's doc comment for why a raw len() here reintroduces the shape-dependent cardinality mismatch this cost model exists to eliminate.

func (*RecordQueryFilterPlan) HintOrdering

func (p *RecordQueryFilterPlan) HintOrdering() properties.Ordering

HintOrdering: a filter preserves its input's order.

func (*RecordQueryFilterPlan) OrderingSourceRef

func (p *RecordQueryFilterPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryFilterPlan) ProvenCardinalities

func (p *RecordQueryFilterPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: a filter may eliminate every row, so the minimum drops to zero; the maximum is inherited.

func (*RecordQueryFilterPlan) WithQuantifiers

WithQuantifiers atomically rebuilds the filter over the replacement child. Its predicates are executable programs over the child edge, so every embedded Value must move to the replacement alias before the new pass-through base is admitted.

type RecordQueryFirstOrDefaultPlan

type RecordQueryFirstOrDefaultPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryFirstOrDefaultPlan takes the first row from the inner plan, or returns a default value if the inner plan produces no rows. Mirrors Java's `RecordQueryFirstOrDefaultPlan`.

When strict is set, the plan additionally enforces the SQL scalar-subquery cardinality rule: if the inner produces MORE THAN ONE row it is a cardinality violation (21000), not a silent truncation to the first row. This is the correlated-scalar-subquery barrier — a non-pushable, per-outer-row check that mirrors the uncorrelated path (executor.EvaluateScalarSubquery). A user-written LIMIT never sets strict: truncation is then the user's deliberate intent.

func NewRecordQueryFirstOrDefaultPlan

func NewRecordQueryFirstOrDefaultPlan(inner RecordQueryPlan, defaultValue values.Value) (*RecordQueryFirstOrDefaultPlan, error)

NewRecordQueryFirstOrDefaultPlan constructs a first-or-default plan over the given inner plan and default value.

func NewRecordQueryFirstOrDefaultPlanFromQuantifier

func NewRecordQueryFirstOrDefaultPlanFromQuantifier(innerQ expressions.Quantifier, defaultValue values.Value) (*RecordQueryFirstOrDefaultPlan, error)

NewRecordQueryFirstOrDefaultPlanFromQuantifier builds a first-or-default whose child is a supplied memo quantifier instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly — the memo holds it without a physicalFirstOrDefaultWrapper (RFC-184 W2).

Unlike DefaultOnEmpty/InJoin (which range over the LIVE shared exploratory group and resolve via ref.Winner()), the FirstOrDefault emitter freezes a DISENTANGLED FINAL reference holding the CONSTRAINT-SATISFYING correlated inner (constraint-preserving disentangle). Its inner is the concrete correlated/SARG member — never the shared-group bare winner — so planFromQuantifier resolves the correlated inner and the correlation on the DML DELETE/UPDATE-WHERE-EXISTS path is preserved. The wrapper's second live edge (which floated to the bare winner and dropped the filter) is gone; the single frozen edge does both jobs.

func NewRecordQueryFirstOrDefaultPlanStrict

func NewRecordQueryFirstOrDefaultPlanStrict(inner RecordQueryPlan, defaultValue values.Value) (*RecordQueryFirstOrDefaultPlan, error)

NewRecordQueryFirstOrDefaultPlanStrict constructs a first-or-default plan that raises a cardinality violation (21000) when the inner yields more than one row.

func NewRecordQueryFirstOrDefaultPlanStrictFromQuantifier

func NewRecordQueryFirstOrDefaultPlanStrictFromQuantifier(innerQ expressions.Quantifier, defaultValue values.Value) (*RecordQueryFirstOrDefaultPlan, error)

NewRecordQueryFirstOrDefaultPlanStrictFromQuantifier is the strict (at-most-one-row → 21000) form of NewRecordQueryFirstOrDefaultPlanFromQuantifier. It preserves BOTH the empty→default value AND the strict cardinality flag.

func (*RecordQueryFirstOrDefaultPlan) EqualsPlanWithoutChildren

func (p *RecordQueryFirstOrDefaultPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryFirstOrDefaultPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryFirstOrDefaultPlan) Explain

Explain renders FirstOrDefault(inner) (StrictFirstOrDefault when strict).

func (*RecordQueryFirstOrDefaultPlan) GetChildren

GetChildren returns the inner plan as the only child.

func (*RecordQueryFirstOrDefaultPlan) GetDefaultValue

func (p *RecordQueryFirstOrDefaultPlan) GetDefaultValue() values.Value

GetDefaultValue returns the fallback value used when the inner plan is empty.

func (*RecordQueryFirstOrDefaultPlan) GetInner

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryFirstOrDefaultPlan) GetInnerQuantifier

func (p *RecordQueryFirstOrDefaultPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single frozen memo edge the first-or-default ranges over. derivationsForFirstOrDefault reads its alias to translate the default value's correlation; since RFC-184 W2 the memo holds the bare plan (no physicalFirstOrDefaultWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryFirstOrDefaultPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryFirstOrDefaultPlan) GetRecordQueryPlan

func (p *RecordQueryFirstOrDefaultPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryFirstOrDefaultPlan) GetResultType

func (p *RecordQueryFirstOrDefaultPlan) GetResultType() values.Type

GetResultType returns the inner's result type.

func (*RecordQueryFirstOrDefaultPlan) GetResultValue

func (p *RecordQueryFirstOrDefaultPlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the child quantifier — a first-or-default passes its input's rows through (with an empty→default row), so its row identity IS the inner's. This is the identity physicalFirstOrDefaultWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryFirstOrDefaultPlan) HashCodeWithoutChildren

func (p *RecordQueryFirstOrDefaultPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryFirstOrDefaultPlan) HintCost

HintCost: at most one row out, the child's work paid in full.

func (*RecordQueryFirstOrDefaultPlan) IsStrict

func (p *RecordQueryFirstOrDefaultPlan) IsStrict() bool

IsStrict reports whether the plan enforces the at-most-one-row scalar-subquery cardinality rule (error 21000 on a second row).

func (*RecordQueryFirstOrDefaultPlan) ProvenCardinalities

ProvenCardinalities: a FirstOrDefault emits the child's first row or the default — exactly one either way, regardless of the child.

func (*RecordQueryFirstOrDefaultPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The first-or-default carries its child as a single frozen memo edge, so the relink is a quantifier swap: WithQuantifiers preserves the default value AND the strict flag, and GetInner re-resolves through the new singleton reference. This replaces physicalFirstOrDefaultWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild gated on isLeafReplaceable. Because the emitter already froze the correlated/SARG inner into a private single-member reference, extraction recurses through it faithfully — it never consults the shared exploratory group, so the correlation cannot be dropped.

func (*RecordQueryFirstOrDefaultPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryFlatMapPlan

type RecordQueryFlatMapPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryFlatMapPlan represents a correlated nested-loop join where for each outer row, the inner plan is re-executed with the outer row bound as a correlation. Mirrors Java's RecordQueryFlatMapPlan which uses FlatMapPipelinedCursor for execution.

The key difference from RecordQueryNestedLoopJoinPlan: the inner plan is parameterized by the outer row via correlation bindings. This enables targeted index probes on the inner side (O(N×logM) vs O(N×M)). LEFT-OUTER note: the plan carries NO leftOuter flag. LEFT-OUTER semantics are emergent from the inner being wrapped in DefaultOnEmpty (whose OrElse continuation makes the null-extension resume-safe), exactly like Java's RecordQueryFlatMapPlan — see rule_implement_nested_loop_join.go's lowering. An earlier in-memory leftOuter/innerHadMatch flag pair re-decided the extension per page and was the F2 spurious-null resume bug; it was removed as dead code.

The two legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQueryFlatMapPlan`'s `Quantifier.Physical outerQuantifier` / `innerQuantifier`). The raw `outer`/`inner` pointers they replace were a second storage location for the same edges. They stay two separately-named fields rather than a slice because the accessors, the Explain rendering and the executor all address them by ROLE, not by position. RFC-183 P5 step 2.

func NewRecordQueryFlatMapPlan

func NewRecordQueryFlatMapPlan(
	outer, inner RecordQueryPlan,
	outerAlias, innerAlias values.CorrelationIdentifier,
	resultValue values.Value,
	inheritOuterRecordProperties bool,
) (*RecordQueryFlatMapPlan, error)

func NewRecordQueryFlatMapPlanFromQuantifiers

func NewRecordQueryFlatMapPlanFromQuantifiers(
	outerQ, innerQ expressions.Quantifier,
	outerAlias, innerAlias values.CorrelationIdentifier,
	resultValue values.Value,
	inheritOuterRecordProperties bool,
) (*RecordQueryFlatMapPlan, error)

NewRecordQueryFlatMapPlanFromQuantifiers builds a correlated FlatMap whose two legs are supplied memo quantifiers instead of snapshots over concrete plans. This makes the plan its own cascades expression carrying its child edges directly — the memo holds it without a physicalFlatMapWrapper (RFC-184 W2).

The FlatMap is the correlation-BINDING operator (CanCorrelate=true): the outer leg binds the value the correlated inner leg re-reads per outer row. The emitter has already decided each leg's edge — a plain/self-contained outer carries the LIVE shared-group edge, while the SARG-pushed/correlated inner is frozen in a detached single-member final reference upstream (the FirstOrDefault / predicates-filter disentangle) — so this constructor is a pure unwrap that carries those edges verbatim. The outer/inner aliases and the result value are preserved so GetResultValue and the correlation propagation stay identical.

func NewRecordQueryFlatMapPlanFromQuantifiersWithNullSupplyingInner

func NewRecordQueryFlatMapPlanFromQuantifiersWithNullSupplyingInner(
	outerQ, innerQ expressions.Quantifier,
	outerAlias, innerAlias values.CorrelationIdentifier,
	resultValue values.Value,
	inheritOuterRecordProperties bool,
) (*RecordQueryFlatMapPlan, error)

NewRecordQueryFlatMapPlanFromQuantifiersWithNullSupplyingInner builds a FlatMap whose inner edge may be absent and therefore supplies SQL NULLs. The fact is explicit at lowering; plans never rediscover it by traversing an executor-specific wrapper spine.

func (*RecordQueryFlatMapPlan) CanCorrelate

func (p *RecordQueryFlatMapPlan) CanCorrelate() bool

CanCorrelate reports that this operator anchors a correlation between its children (the outer leg binds the value the inner leg reads), mirroring physicalFlatMapWrapper.

func (*RecordQueryFlatMapPlan) EqualsPlanWithoutChildren

func (p *RecordQueryFlatMapPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryFlatMapPlan) EqualsWithoutChildren

func (p *RecordQueryFlatMapPlan) EqualsWithoutChildren(other expressions.RelationalExpression, aliases *expressions.AliasMap) bool

EqualsWithoutChildren compares child-local aliases, the result program and its physical output layout through the memo's alpha-renaming.

func (*RecordQueryFlatMapPlan) Explain

func (p *RecordQueryFlatMapPlan) Explain() string

Explain renders both legs UNGUARDED, exactly as the raw-pointer form did: a nil leg panics here rather than rendering "<nil>". That is deliberate — a FlatMap with a missing leg is not a renderable plan, and quietly printing a placeholder would hide it. Whether to soften this is a separate decision.

func (*RecordQueryFlatMapPlan) GetChildren

func (p *RecordQueryFlatMapPlan) GetChildren() []RecordQueryPlan

GetChildren returns the outer leg then the inner leg, dereferenced through the quantifiers. The pair is always two entries wide — a nil leg stays a nil entry rather than shrinking the arity, which is what the executor's positional child handling expects.

func (*RecordQueryFlatMapPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryFlatMapPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren walks this plan's own result value, mirroring the way the NestedLoopJoin walks its predicates. A FlatMap is the correlation-binding operator (CanCorrelate=true): its merged/projected result value is the node's own information and may reference a genuinely-EXTERNAL correlation (an enclosing FlatMap's outer row) that is reachable through nothing but this value. The framework subtracts this node's own leg aliases (expressionCorrelatedTo), so only real external correlations survive — but they MUST be reported, or a correlation-driven rule would hoist this FlatMap as if it were self-contained and drop the correlation. The retired physicalFlatMapWrapper returned the empty set here and deferred exactly this propagation (RFC-184 W2); the bare plan owns its result value, so it does the walk the wrapper could not.

func (*RecordQueryFlatMapPlan) GetInner

func (*RecordQueryFlatMapPlan) GetInnerAlias

func (*RecordQueryFlatMapPlan) GetOuter

func (*RecordQueryFlatMapPlan) GetOuterAlias

func (*RecordQueryFlatMapPlan) GetQuantifiers

func (p *RecordQueryFlatMapPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real leg quantifiers in GetChildren order (outer, inner), overriding PlanExprBase's none. That order is what WithQuantifiers indexes into.

func (*RecordQueryFlatMapPlan) GetRecordQueryPlan

func (p *RecordQueryFlatMapPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryFlatMapPlan) GetResultType

func (p *RecordQueryFlatMapPlan) GetResultType() values.Type

func (*RecordQueryFlatMapPlan) GetResultValue

func (p *RecordQueryFlatMapPlan) GetResultValue() values.Value

func (*RecordQueryFlatMapPlan) HashCodeWithoutChildren

func (p *RecordQueryFlatMapPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryFlatMapPlan) HintCost

HintCost: a correlated dependent join re-runs the inner once per outer row.

func (*RecordQueryFlatMapPlan) HintOrdering

func (p *RecordQueryFlatMapPlan) HintOrdering() properties.Ordering

HintOrdering: a dependent join's output order is not modeled.

func (*RecordQueryFlatMapPlan) InheritOuterRecordProperties

func (p *RecordQueryFlatMapPlan) InheritOuterRecordProperties() bool

func (*RecordQueryFlatMapPlan) ProvenCardinalities

ProvenCardinalities: outer x inner, exactly as Java's visitRecordQueryFlatMapPlan multiplies the two legs.

func (*RecordQueryFlatMapPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The FlatMap carries its two legs as memo quantifiers, so the relink keeps the outer/inner runtime aliases but re-resolves their retained result roots against the replacement children's exact types, then rebuilds the provided output layout (including the null-supplying-inner marker). This replaces physicalFlatMapWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field held the yield-time children verbatim; the swap re-resolves to the memo winner instead. The correlated inner is preserved because the emitter already froze it into a private single-member reference upstream — extraction recurses through that frozen edge and never consults the shared exploratory group.

func (*RecordQueryFlatMapPlan) WithQuantifiers

WithQuantifiers atomically rebuilds the FlatMap over the replacement legs. outerAlias and innerAlias are the runtime binding identities; they therefore stay fixed even though extraction gives each child edge a fresh quantifier alias. The retained result program is re-resolved at those logical aliases against the selected children's exact carrier types. An alias-only shallow copy would retain a logical/previous-phase root type that the executor cannot bind to the selected physical row.

type RecordQueryInJoinPlan

type RecordQueryInJoinPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryInJoinPlan executes its inner plan once for each value from an IN-source, binding the value to a correlation variable. The result is the concatenation of all inner executions.

Mirrors Java's RecordQueryInJoinPlan hierarchy (InValuesJoin, InParameterJoin, InComparandJoin).

func NewRecordQueryInJoinPlan

func NewRecordQueryInJoinPlan(
	inner RecordQueryPlan,
	bindingName string,
	sorted bool,
	reverse bool,
) (*RecordQueryInJoinPlan, error)

func NewRecordQueryInJoinPlanFromQuantifier

func NewRecordQueryInJoinPlanFromQuantifier(
	innerQ expressions.Quantifier,
	bindingName string,
	sorted bool,
	reverse bool,
) (*RecordQueryInJoinPlan, error)

NewRecordQueryInJoinPlanFromQuantifier builds the InJoin over the LIVE inner quantifier the implement rule memoized, rather than over a plan snapshot. The inner is a SHARED group whose per-ordering winner resolves at extraction via ref.Winner() (planFromQuantifier) — the deferred-winner case. The plan carries the inner edge once, with no wrapper snapshot (RFC-184 W2). Callers still replay WithInValues / WithSourceKind afterward (the constructor drops them).

func NewRecordQueryInJoinPlanFromQuantifierWithBindingAlias

func NewRecordQueryInJoinPlanFromQuantifierWithBindingAlias(
	innerQ expressions.Quantifier,
	bindingAlias values.CorrelationIdentifier,
	sorted bool,
	reverse bool,
) (*RecordQueryInJoinPlan, error)

func NewRecordQueryInJoinPlanWithBindingAlias

func NewRecordQueryInJoinPlanWithBindingAlias(
	inner RecordQueryPlan,
	bindingAlias values.CorrelationIdentifier,
	sorted bool,
	reverse bool,
) (*RecordQueryInJoinPlan, error)

NewRecordQueryInJoinPlanWithBindingAlias preserves the exact correlation kind of the IN binding. Planner-minted q$ aliases are Unique identifiers; a string round-trip remints them as Named identifiers with the same rendering, which exact QOV lookup correctly treats as a different runtime binding.

func (*RecordQueryInJoinPlan) EqualsPlanWithoutChildren

func (p *RecordQueryInJoinPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryInJoinPlan) EqualsWithoutChildren

func (p *RecordQueryInJoinPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryInJoinPlan) Explain

func (p *RecordQueryInJoinPlan) Explain() string

func (*RecordQueryInJoinPlan) GetBindingAlias

func (p *RecordQueryInJoinPlan) GetBindingAlias() values.CorrelationIdentifier

func (*RecordQueryInJoinPlan) GetBindingName

func (p *RecordQueryInJoinPlan) GetBindingName() string

func (*RecordQueryInJoinPlan) GetChildren

func (p *RecordQueryInJoinPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryInJoinPlan) GetInValues

func (p *RecordQueryInJoinPlan) GetInValues() []any

GetInValues returns the LIVE slice; callers must not write through it. inValues is in this plan's structuralKey, so an element write rewrites its identity with the pointer unchanged, which the memo's owner check cannot see. It is not copied here because cost.go reads it per costing call in the planner's hot loop; sharing is broken at the write end instead (see WithInValues).

func (*RecordQueryInJoinPlan) GetInner

func (p *RecordQueryInJoinPlan) GetInner() RecordQueryPlan

func (*RecordQueryInJoinPlan) GetInnerQuantifier

func (p *RecordQueryInJoinPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the InJoin ranges over. derivationsForInJoin reads its alias to decorrelate the inner against the IN-source; since RFC-184 W2 the memo holds the bare plan (no physicalInJoinWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryInJoinPlan) GetQuantifiers

func (p *RecordQueryInJoinPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryInJoinPlan) GetRecordQueryPlan

func (p *RecordQueryInJoinPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryInJoinPlan) GetResultType

func (p *RecordQueryInJoinPlan) GetResultType() values.Type

func (*RecordQueryInJoinPlan) GetResultValue

func (p *RecordQueryInJoinPlan) GetResultValue() values.Value

GetResultValue flows the live child quantifier's object value — the InJoin emits its inner's rows once per IN-source value, so its row identity IS the inner's. This is the identity physicalInJoinWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryInJoinPlan) GetSourceKind

func (p *RecordQueryInJoinPlan) GetSourceKind() InSourceKind

func (*RecordQueryInJoinPlan) HashCodeWithoutChildren

func (p *RecordQueryInJoinPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryInJoinPlan) HintCost

HintCost: an InJoin re-runs its inner once per IN value. ImplementInJoinRule (rule_implement_in_join.go) matches ANY equality-bound inner — a unique index, a full primary-key bind, OR a non-unique secondary index — so "the inner does an equality point-lookup returning ~1 row" is only sound when isProvablePointProbe proves it. When it does, the IN-list length IS the output cardinality and each value pays TWO isolated, unamortized round trips — the index equality point-probe itself (ONE GetRange bound to that value, no batching across IN values) and the base-record fetch it resolves — the same physical shape properties.FetchCPU's doc comment establishes for any isolated point-probe/fetch, not the amortized multi-row ScanCPU rate.

When it is NOT a provable point probe (e.g. `category IN ('a','b','c')` over a non-unique index), the child's own cardinality is the per-probe row count and must NOT be discarded — the same principle plan_properties.go's computeCardinalities uses for RecordQueryInJoinPlan (inSize.Times(child.GetMaxCardinality())) and RecordQueryInUnionPlan. HintCost already applies below. FlatMapCost is the exact right shape for this: the IN-list is a synthetic, free-to-produce "outer" of inListLen rows (RecordQueryValuesPlan.HintCost prices a literal row source at CPU 0) driving one execution of the SAME inner per row — precisely what a correlated dependent join costs.

func (*RecordQueryInJoinPlan) HintOrdering

func (p *RecordQueryInJoinPlan) HintOrdering() properties.Ordering

HintOrdering: an InJoin iterates IN-values one at a time. Each batch preserves the inner scan's ordering, but the GLOBAL result ordering depends on the IN-source order, not the inner scan. Claiming the inner's ordering would let sort elimination remove a necessary ORDER BY.

func (*RecordQueryInJoinPlan) IsReverse

func (p *RecordQueryInJoinPlan) IsReverse() bool

func (*RecordQueryInJoinPlan) IsSorted

func (p *RecordQueryInJoinPlan) IsSorted() bool

func (*RecordQueryInJoinPlan) ProvenCardinalities

func (p *RecordQueryInJoinPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: the inner runs once per IN value, so both bounds scale by the in-list length. An in-list whose size is not known at plan time proves nothing.

func (*RecordQueryInJoinPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the InJoin carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves every other field (inValues, sourceKind, sorted, reverse, bindingName) and GetInner re-resolves through the new singleton reference. This replaces physicalInJoinWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a WithInner rebuild gated on isLeafReplaceable — a single live child edge relinks to ref.Winner() unconditionally.

func (*RecordQueryInJoinPlan) WithInValues

func (p *RecordQueryInJoinPlan) WithInValues(vals []any) *RecordQueryInJoinPlan

WithInValues and WithSourceKind return COPIES, because a plan method must never write through its receiver.

inValues is in this plan's structuralKey, so an in-place write rewrites the identity of a plan the memo may already hold — under an UNCHANGED owner, which the structural-hash memo's owner check cannot detect, because it compares identity and not content. sourceKind is NOT in the key and was therefore harmless; it copies too, so the rule is "a plan method does not write its receiver" with no per-field exception a reader has to look up.

func (*RecordQueryInJoinPlan) WithInner

WithInner returns a copy with the inner replaced and EVERY other field preserved — the extraction-relink rebuild path; reconstructing via the constructor risks silently dropping fields the setters carry.

func (*RecordQueryInJoinPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

func (*RecordQueryInJoinPlan) WithSourceKind

type RecordQueryInMemorySortPlan

type RecordQueryInMemorySortPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryInMemorySortPlan materializes the inner plan's output and sorts it in memory.

Go extension — Java's Cascades has no physical sort operator.

Cascades still optimizes the inner plan (index scans, predicate pushdown, join ordering). Only the final sort is post-processed. The cost model ensures index-based sort elimination is preferred when an index exists.

func NewRecordQueryInMemorySortPlan

func NewRecordQueryInMemorySortPlan(inner RecordQueryPlan, sortKeys []SortKey) (*RecordQueryInMemorySortPlan, error)

func NewRecordQueryInMemorySortPlanFromQuantifier

func NewRecordQueryInMemorySortPlanFromQuantifier(innerQ expressions.Quantifier, sortKeys []SortKey) (*RecordQueryInMemorySortPlan, error)

NewRecordQueryInMemorySortPlanFromQuantifier builds an in-memory sort whose child is a supplied memo quantifier instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly — the memo holds it without a physicalInMemorySortWrapper (RFC-184 W2).

The sort RE-SORTS its input, so it does not care what order the child provides: unlike the ordering-DELEGATOR wrappers (which pin an ordered spine), it only needs the cheapest VALID child member for ANY ordering. When the emitter hands it the LIVE shared-group edge (ForEachQuantifier(innerRef)), GetInner resolves through planFromQuantifier → innerRef.Winner() — the group's OPTIMIZE-chosen cheapest member (unified_tasks.OptimizeGroupTask stamps the overall cost winner, ordering-agnostic). Cost (concretePlanCounts walks GetChildren → GetInner) and extraction (rebuild recurses the same edge) therefore resolve the SAME member, closing the cost-over-first / extract-over-best gap the wrapper carried (plan_expression.go's planFromQuantifier note). The sort keys are copied so the provided ordering (HintOrdering) stays stable across relinks.

func (*RecordQueryInMemorySortPlan) EqualsPlanWithoutChildren

func (p *RecordQueryInMemorySortPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryInMemorySortPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryInMemorySortPlan) Explain

func (p *RecordQueryInMemorySortPlan) Explain() string

func (*RecordQueryInMemorySortPlan) GetChildren

func (p *RecordQueryInMemorySortPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryInMemorySortPlan) GetInner

func (*RecordQueryInMemorySortPlan) GetInnerQuantifier

func (p *RecordQueryInMemorySortPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the sort ranges over. Since RFC-184 W2 the memo holds the bare plan (no physicalInMemorySortWrapper whose innerQuant field was read), this exposes the same edge for derivations and extraction.

func (*RecordQueryInMemorySortPlan) GetQuantifiers

func (p *RecordQueryInMemorySortPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryInMemorySortPlan) GetRecordQueryPlan

func (p *RecordQueryInMemorySortPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryInMemorySortPlan) GetResultType

func (p *RecordQueryInMemorySortPlan) GetResultType() values.Type

GetResultType returns the inner plan's result type: an in-memory sort reorders rows but preserves the inner's row shape, so it flows the inner's type through (matching pass-through plans like Filter / Fetch). Nil inner degrades to UnknownType.

func (*RecordQueryInMemorySortPlan) GetSortKeys

func (p *RecordQueryInMemorySortPlan) GetSortKeys() []SortKey

GetSortKeys returns the LIVE key slice, and the caller must not write through it. `sortKeys` is folded into structuralKey and `SortKey`'s fields are exported, so `GetSortKeys()[0].Desc = true` rewrites this plan's identity with its pointer unchanged — the one staleness the structural-hash memo's owner check cannot detect, because it compares identity and not content.

It returns the live slice rather than a copy because the readers are the planner's hot loop: the cost model iterates these keys per candidate (planning_cost_model.go), as do the ordering rules, and a per-call allocation there taxes the exact path the memo was added to relieve. Sharing is instead broken at the WRITE end — constructors copy — so no two plans own one array.

func (*RecordQueryInMemorySortPlan) HashCodeWithoutChildren

func (p *RecordQueryInMemorySortPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryInMemorySortPlan) HintCost

HintCost: materialize + O(n log n), with NO physical discount so an in-memory sort stays strictly more expensive than index-based elimination.

func (*RecordQueryInMemorySortPlan) HintOrdering

HintOrdering: an in-memory sort produces exactly its sort keys. NULL placement is carried so a parent sort does not elide against a counterflow (e.g. ASC NULLS LAST) stream as if it were natural order.

func (*RecordQueryInMemorySortPlan) ProvenCardinalities

ProvenCardinalities: a sort reorders rows, it never adds or removes them.

func (*RecordQueryInMemorySortPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The sort carries its child as a single memo edge, so the relink is a quantifier swap: WithQuantifiers copies the receiver (preserving the sort keys) and re-resolves GetInner through the new singleton reference. This replaces physicalInMemorySortWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a findBestPhysicalPlan constructor rebuild. Because extraction hands qs[0] the child group's already-resolved winner (a singleton holding the cheapest member), a pure quantifier swap resolves the exact plan the cost model costed — no separate best-member re-pick is needed.

func (*RecordQueryInMemorySortPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryInUnionPlan

type RecordQueryInUnionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryInUnionPlan is the IN-union variant: the inner plan is executed once per Cartesian-product combination of IN-source bindings, and results are merge-sorted by comparison keys. Mirrors Java's RecordQueryInUnionOnValuesPlan.

func NewRecordQueryInUnionPlan

func NewRecordQueryInUnionPlan(
	inner RecordQueryPlan,
	bindingNames []string,
	comparisonKeys []values.Value,
	reverse bool,
) (*RecordQueryInUnionPlan, error)

func NewRecordQueryInUnionPlanFromQuantifier

func NewRecordQueryInUnionPlanFromQuantifier(
	innerQ expressions.Quantifier,
	bindingNames []string,
	comparisonKeys []values.Value,
	reverse bool,
	maxSize int,
) (*RecordQueryInUnionPlan, error)

NewRecordQueryInUnionPlanFromQuantifier builds the InUnion over the LIVE inner quantifier the implement rule memoized, rather than over a plan snapshot. The inner may be a SHARED multi-member group (the unordered path) whose per-ordering winner resolves at extraction via ref.Winner() (planFromQuantifier) — the deferred-winner case. The plan carries the inner edge once, with no wrapper snapshot (RFC-184 W2). Callers still replay WithInSources afterward.

func NewRecordQueryInUnionPlanFromQuantifierWithBindingAliases

func NewRecordQueryInUnionPlanFromQuantifierWithBindingAliases(
	innerQ expressions.Quantifier,
	bindingAliases []values.CorrelationIdentifier,
	comparisonKeys []values.Value,
	reverse bool,
	maxSize int,
) (*RecordQueryInUnionPlan, error)

func NewRecordQueryInUnionPlanWithBindingAliases

func NewRecordQueryInUnionPlanWithBindingAliases(
	inner RecordQueryPlan,
	bindingAliases []values.CorrelationIdentifier,
	comparisonKeys []values.Value,
	reverse bool,
) (*RecordQueryInUnionPlan, error)

NewRecordQueryInUnionPlanWithBindingAliases preserves the exact correlation kind of every IN binding. Planner-minted aliases are Unique identifiers; a string round-trip remints them as Named identifiers with the same spelling, which exact QOV lookup correctly treats as a different binding.

func NewRecordQueryInUnionPlanWithBindingAliasesAndMaxSize

func NewRecordQueryInUnionPlanWithBindingAliasesAndMaxSize(
	inner RecordQueryPlan,
	bindingAliases []values.CorrelationIdentifier,
	comparisonKeys []values.Value,
	reverse bool,
	maxSize int,
) (*RecordQueryInUnionPlan, error)

func (*RecordQueryInUnionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryInUnionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryInUnionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryInUnionPlan) Explain

func (p *RecordQueryInUnionPlan) Explain() string

func (*RecordQueryInUnionPlan) GetBindingAliases

func (p *RecordQueryInUnionPlan) GetBindingAliases() []values.CorrelationIdentifier

func (*RecordQueryInUnionPlan) GetBindingNames

func (p *RecordQueryInUnionPlan) GetBindingNames() []string

func (*RecordQueryInUnionPlan) GetChildren

func (p *RecordQueryInUnionPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryInUnionPlan) GetComparisonKeys

func (p *RecordQueryInUnionPlan) GetComparisonKeys() []values.Value

func (*RecordQueryInUnionPlan) GetInSources

func (p *RecordQueryInUnionPlan) GetInSources() [][]any

GetInSources returns the LIVE slice; callers must not write through it. See WithInSources for why sharing is broken at the write end rather than here: cost.go reads these per costing call, so a defensive copy would sit in the planner's hot loop.

func (*RecordQueryInUnionPlan) GetInner

func (*RecordQueryInUnionPlan) GetInnerQuantifier

func (p *RecordQueryInUnionPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the InUnion ranges over. derivationsForInUnion reads its alias to decorrelate the inner against the IN-source bindings; since RFC-184 W2 the memo holds the bare plan (no physicalInUnionWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryInUnionPlan) GetMaxSize

func (p *RecordQueryInUnionPlan) GetMaxSize() int

func (*RecordQueryInUnionPlan) GetQuantifiers

func (p *RecordQueryInUnionPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryInUnionPlan) GetRecordQueryPlan

func (p *RecordQueryInUnionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryInUnionPlan) GetResultType

func (p *RecordQueryInUnionPlan) GetResultType() values.Type

func (*RecordQueryInUnionPlan) GetResultValue

func (p *RecordQueryInUnionPlan) GetResultValue() values.Value

GetResultValue flows the live child quantifier's object value — the InUnion emits its inner's rows once per IN-source binding, so its row identity IS the inner's. This is the identity physicalInUnionWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryInUnionPlan) HashCodeWithoutChildren

func (p *RecordQueryInUnionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryInUnionPlan) HintCost

HintCost: an InUnion runs its child once per Cartesian-product IN-binding combination. Literal sources have an exact fanout; each source unavailable at planning time contributes the conservative default of 10 values. A single exact combination executes the child directly, so it must not receive an artificial wrapper discount.

func (*RecordQueryInUnionPlan) HintOrdering

func (p *RecordQueryInUnionPlan) HintOrdering() properties.Ordering

HintOrdering: an InUnion emits rows in its comparison-key order, in the direction it merges its per-binding legs.

The reverse flag IS the direction of every comparison key: the rules that build these merges refuse any candidate whose parts do not all agree with it (properties.NaturalComparisonKeyValues), because the executable comparison key is the raw Value and a key read forward cannot express a descending component. Reporting the keys without their direction advertised a descending merge as ascending, so a matching ORDER BY DESC saw its own access path as unsatisfying and kept an in-memory sort over it.

func (*RecordQueryInUnionPlan) IsReverse

func (p *RecordQueryInUnionPlan) IsReverse() bool

func (*RecordQueryInUnionPlan) LiteralFanout

func (p *RecordQueryInUnionPlan) LiteralFanout() (fanout int64, known bool)

LiteralFanout returns the exact number of child executions represented by the plan-time IN sources. Each source is one binding dimension, so the fanout is their Cartesian-product size. A nil inner source in a present dimension means its runtime value was unavailable during planning and therefore returns known=false; a non-nil empty source is an exact zero. An absent outer source slice is a pass-through, even when binding names exist; executeInUnion has always used that constructor shape to mean "no materialized sources." Once sources are present, their dimension count must equal the binding count.

Overflow also returns unknown instead of wrapping to a negative cardinality.

func (*RecordQueryInUnionPlan) ProvenCardinalities

ProvenCardinalities: the child runs once per Cartesian-product IN-binding combination, so both bounds scale by the literal fanout.

A known-EMPTY dimension proves exactly zero even when another dimension is runtime-unknown: the executor returns an empty cursor. Java's generic unknown multiplication keeps that mixed maximum unknown; exact zero is stronger but sound, and it is a deliberate Go precision extension.

func (*RecordQueryInUnionPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the InUnion carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves every other field (bindingNames, comparisonKeys, reverse, maxSize, inSources) and GetInner re-resolves through the new singleton reference. This replaces physicalInUnionWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a WithInner rebuild gated on isLeafReplaceable — a single live child edge relinks to ref.Winner() unconditionally.

func (*RecordQueryInUnionPlan) WithInSources

func (p *RecordQueryInUnionPlan) WithInSources(sources [][]any) *RecordQueryInUnionPlan

WithInSources returns a COPY carrying the materialized IN sources, because a plan method must never write through its receiver.

inSources is in this plan's structuralKey, so writing it in place rewrites the identity of a plan that may already be in the memo — and since the structural-hash memo landed, under an UNCHANGED owner, which is the one staleness the memo's owner check cannot see: it compares identity, not content. Every caller happened to set before yielding, so nothing was ever wrong; that is exactly the "guarded by accident" shape, with no rule keeping it true.

Scope of that claim, because an unscoped count is the thing this repo keeps getting wrong: across WithInValues, WithSourceKind and WithInSources together, 8 invocations in NON-TEST sources, spread over 4 rule files and 4 enclosing functions. An earlier draft said "five call sites", which is not the count under any definition.

Deliberately no test-inclusive total here. A first correction added one, and it was false on arrival: the very commit that wrote "40 invocations including tests" went on to add five more test arms, so the number was stale before it was pushed. A figure that moves whenever anyone writes a test cannot stay true in a comment. The non-test count is the one that means something — it is the set that has to be audited when this rule changes — and it is stable.

func (*RecordQueryInUnionPlan) WithInner

WithInner returns a copy with the inner replaced and EVERY other field preserved (bindingNames, comparisonKeys, reverse, maxSize, inSources) — the extraction-relink rebuild path.

func (*RecordQueryInUnionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryIndexPlan

type RecordQueryIndexPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryIndexPlan is an index scan over a secondary index — reads index entries whose key prefix satisfies the scan comparisons, then fetches the corresponding records. Mirrors Java's `RecordQueryIndexPlan`.

Seed surface:

  • IndexName: name of the index being scanned.
  • ScanComparisons: ordered list of ComparisonRanges (one per index key column, left-to-right). The prefix defines the FDB key range: equality ranges become exact prefix bytes, the first inequality becomes range bounds, and the rest are empty (full scan for those suffix columns).
  • RecordTypes: which record types the index covers.
  • Reverse: scan direction.
  • FlowedType: rich Type of the row stream.

The index scan is a LEAF in the plan tree — it reads directly from FDB (the index subspace). A follow-up fetch step may be needed if the index is non-covering; that lands as a separate plan node (RecordQueryFetchFromPartialRecordPlan in Java) when covering-index rules port.

func IndexPlanOf

func IndexPlanOf(node RecordQueryPlan) (*RecordQueryIndexPlan, bool)

IndexPlanOf returns the index scan node reads entries from, seeing through a covering wrapper, and reports whether node is an index scan at all.

This is the exported form of a helper that had been written twice as an unexported test helper in two different packages (`indexScanOf` in package embedded, `indexScanOfNode` in package sqldriver_test) precisely because there was no importable symbol to share. It is exported for that reason as much as for use in the tree: a guard against a structural blindness that cannot be shared is a guard that gets re-derived, and re-derived wrong.

A carrier whose inner scan is nil reports FALSE rather than (nil, true). The constructors never produce one, but a struct-literal plan can, and a caller that gets ok=true proceeds to dereference — turning a malformed test fixture into a nil panic far from its cause instead of a clean "not an index scan".

func NewRecordQueryIndexPlan

func NewRecordQueryIndexPlan(
	indexName string,
	scanComparisons []*predicates.ComparisonRange,
	recordTypes []string,
	flowedType values.Type,
	reverse bool,
) (*RecordQueryIndexPlan, error)

NewRecordQueryIndexPlan constructs an index scan plan.

func (*RecordQueryIndexPlan) AllCoveredEntryColumns

func (p *RecordQueryIndexPlan) AllCoveredEntryColumns() []string

AllCoveredEntryColumns returns the entry's column names in ENTRY layout order — key columns, then the KeyWithValue VALUE part — the list the covering executor aligns positionally against (index key values ++ entry value tuple).

func (*RecordQueryIndexPlan) EqualsPlanWithoutChildren

func (p *RecordQueryIndexPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryIndexPlan) EqualsWithoutChildren

func (p *RecordQueryIndexPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryIndexPlan) Explain

func (p *RecordQueryIndexPlan) Explain() string

Explain renders a one-line label. A bare index scan is never covering — a covering scan is a distinct plan type wrapping this one, and it renders through explainWithCovering.

func (*RecordQueryIndexPlan) GetChildren

func (p *RecordQueryIndexPlan) GetChildren() []RecordQueryPlan

GetChildren returns nil — index scans are leaves.

func (*RecordQueryIndexPlan) GetColumnNames

func (p *RecordQueryIndexPlan) GetColumnNames() []string

GetColumnNames returns the index's key column names, in index-key order.

func (*RecordQueryIndexPlan) GetCommonPrimaryKeyValues

func (p *RecordQueryIndexPlan) GetCommonPrimaryKeyValues() []values.Value

GetCommonPrimaryKeyValues returns the index's structural common primary key (RFC-189 B3), or nil when unknown/abstaining.

func (*RecordQueryIndexPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryIndexPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren reports the correlations reached through this scan's comparison operands, mirroring physicalIndexScanWrapper.

func (*RecordQueryIndexPlan) GetDistinctProofIndexName

func (p *RecordQueryIndexPlan) GetDistinctProofIndexName() string

GetDistinctProofIndexName implements DistinctProofStamped. An ORDER-BY'd `SELECT DISTINCT <unique column>` elides its DISTINCT over an INDEX scan, so the index plan is a carrier too — and the index it SCANS need not be the index that PROVED the elision, which is why the stamp is its own field rather than being read back off indexName.

func (*RecordQueryIndexPlan) GetFlowedType

func (p *RecordQueryIndexPlan) GetFlowedType() values.Type

GetFlowedType returns the rich row Type.

func (*RecordQueryIndexPlan) GetIndexName

func (p *RecordQueryIndexPlan) GetIndexName() string

GetIndexName returns the index name.

func (*RecordQueryIndexPlan) GetIndexPlan

func (p *RecordQueryIndexPlan) GetIndexPlan() *RecordQueryIndexPlan

GetIndexPlan returns the receiver: a bare index scan IS the index scan it reads entries from. Having the bare plan answer the same question as the covering wrapper is the whole point — it lets a caller be written once, against the carrier, instead of twice against the two concrete types.

func (*RecordQueryIndexPlan) GetKeyComponentTypes

func (p *RecordQueryIndexPlan) GetKeyComponentTypes() []values.Type

GetKeyComponentTypes returns physical types aligned with index-key coordinates; the vector can be longer than GetScanComparisons.

func (*RecordQueryIndexPlan) GetPKColumnNames

func (p *RecordQueryIndexPlan) GetPKColumnNames() []string

GetPKColumnNames returns the record type's primary-key column names.

func (*RecordQueryIndexPlan) GetPrimaryKeyComponentTypes

func (p *RecordQueryIndexPlan) GetPrimaryKeyComponentTypes() []values.Type

GetPrimaryKeyComponentTypes returns physical types aligned with the untrimmed primary-key column metadata.

func (*RecordQueryIndexPlan) GetRecordQueryPlan

func (p *RecordQueryIndexPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryIndexPlan) GetRecordTypes

func (p *RecordQueryIndexPlan) GetRecordTypes() []string

GetRecordTypes returns the covered record types.

func (*RecordQueryIndexPlan) GetResultType

func (p *RecordQueryIndexPlan) GetResultType() values.Type

GetResultType returns the row Type.

func (*RecordQueryIndexPlan) GetResultValue

func (p *RecordQueryIndexPlan) GetResultValue() values.Value

GetResultValue returns the index scan's STABLE per-instance result value — the single correlation identity a bare index scan carries as its own memo expression (RFC-184 W2). Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryIndexPlan) GetScanComparisons

func (p *RecordQueryIndexPlan) GetScanComparisons() []*predicates.ComparisonRange

GetScanComparisons returns the per-column comparison ranges.

func (*RecordQueryIndexPlan) GetValueColumnNames

func (p *RecordQueryIndexPlan) GetValueColumnNames() []string

GetValueColumnNames returns the covering-only (FDB VALUE part) columns of a KeyWithValue-rooted index, or nil.

func (*RecordQueryIndexPlan) HashCodeWithoutChildren

func (p *RecordQueryIndexPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryIndexPlan) HintCost

HintCost: index scans are cheaper than full table scans because they read a subset of records. Apply a selectivity multiplier on top of the physical discount. A fully equality-bound UNIQUE index gets the exact physical-key multiplicity when provable: normally one, 2^k for k known signed-zero float components, and unknown for NULL under NULLS-DISTINCT uniqueness or for a dynamic float comparand.

The point-lookup branch charges FetchCPU for the INDEX round trip itself — it is ONE isolated GetRange call with nothing to amortize over, the same physical shape as a Fetch (see properties.FetchCPU's doc comment). This is NOT the base-record fetch: that per-row cost still belongs on the separate Fetch enforcer (eliminated for covering scans), added on TOP of this when the index is non-covering — a covering unique-index point-probe (no Fetch node) correctly costs one round trip; a non-covering one correctly costs two.

func (*RecordQueryIndexPlan) HintOrdering

func (p *RecordQueryIndexPlan) HintOrdering() properties.Ordering

HintOrdering: an index scan produces rows in index-key order for the non-equality-bound suffix columns, extended by the trimmed primary-key suffix (index entries are (index key, primary key), so the PK columns continue the sort order). E.g. index(a, b, c) with a = 1 over PK (id) produces output sorted by (b, c, id). Mirrors the full-key ordering of Java's ValueIndexLikeMatchCandidate.computeOrderingFromScanComparisons.

func (*RecordQueryIndexPlan) HintRichOrdering

func (p *RecordQueryIndexPlan) HintRichOrdering() *properties.RichOrdering

HintRichOrdering returns the index scan's full ordering with bindings: equality-bound prefix columns become FixedBinding entries (carrying the comparison), non-equality suffix columns become SortedBinding entries. The trimmed primary-key suffix continues the sorted keys — this is what lets an equality-prefixed scan (status = ?) satisfy ORDER BY pk, exactly as Java's ValueIndexLikeMatchCandidate.computeOrderingFromScanComparisons derives the ordering over getFullKeyExpression() (index key + trimmed PK) with Binding.fixed for the equality prefix and Binding.sorted for the rest.

Note this differs from HintOrdering, which DROPS the equality prefix entirely; here the prefix is retained as fixed, which is strictly more information.

func (*RecordQueryIndexPlan) IsReverse

func (p *RecordQueryIndexPlan) IsReverse() bool

IsReverse reports the scan direction.

func (*RecordQueryIndexPlan) IsStrictlySorted

func (p *RecordQueryIndexPlan) IsStrictlySorted() bool

IsStrictlySorted reports whether the scan's ordering uniquely determines each record (no two adjacent records share the same key). Set by RemoveSortRule when DISTINCT covers all ordering keys or a unique index satisfies the full key set.

func (*RecordQueryIndexPlan) IsUnique

func (p *RecordQueryIndexPlan) IsUnique() bool

IsUnique reports whether the scanned index is declared UNIQUE.

func (*RecordQueryIndexPlan) ProducesDistinctRecords

func (p *RecordQueryIndexPlan) ProducesDistinctRecords() bool

ProducesDistinctRecords ports Java DistinctRecordsProperty.visitIndexPlan: an index scan produces distinct records iff its match candidate did NOT create duplicates. Until the signal is stamped (no candidate) it returns false — Java's empty-candidate default. Independent of UNIQUE: a non-unique scalar index does not create duplicates and so IS distinct.

func (*RecordQueryIndexPlan) ProvenCardinalities

ProvenCardinalities: a UNIQUE index with every one of its columns equality-bound has an exact physical multiplicity only when every equality class is bounded. It is normally one, but known signed-zero components form a checked Cartesian set and nullable NULLS-DISTINCT binds remain unknown.

A WIDENING equality does not pin a single key. The executor widens a zero-valued float bound across both signed zeros (-0.0 and +0.0 are IEEE-equal but pack to distinct adjacent keys), and a UNIQUE index legitimately holds BOTH — uniqueness is enforced on the raw packed prefix, so the two are different entries. Measured: a unique index on a DOUBLE column holding both zeros returns TWO rows for `WHERE v = 0`. The shared multiplicity proof therefore returns two (and multiplies independent components) instead of the retired false one.

The check uses the SHARED widening predicate deliberately: a correlated or Unknown-typed operand — the QOV a multi-element float IN list produces — is not constant, yet the executor can still widen a zero binding at runtime. The matcher's constant-only helper is not runtime-safe, and using it here left the false proof reachable through exactly those operands.

This arm counts EVERY comparison (including empty trailing ranges) rather than only the non-empty bound prefix. A trailing unconstrained column therefore declines the proof; a declined proof only forgoes a clamp, while a granted one caps an estimate.

func (*RecordQueryIndexPlan) WithCommonPrimaryKey

func (p *RecordQueryIndexPlan) WithCommonPrimaryKey(pk []values.Value) *RecordQueryIndexPlan

WithCommonPrimaryKey returns a copy carrying the index's structural common primary key (RFC-189 B3). Shallow copy (cp := *p) so every other field auto-carries.

func (*RecordQueryIndexPlan) WithDistinctProofIndexName

func (p *RecordQueryIndexPlan) WithDistinctProofIndexName(indexName string) RecordQueryPlan

WithDistinctProofIndexName implements DistinctProofStampable.

func (*RecordQueryIndexPlan) WithDistinctRecordsSignal

func (p *RecordQueryIndexPlan) WithDistinctRecordsSignal(createsDuplicates bool) *RecordQueryIndexPlan

WithDistinctRecordsSignal stamps the match candidate's fan-out signal onto a shallow copy (Java DistinctRecordsProperty). Call it when building an index plan from a candidate that exposes createsDuplicates(); it marks the signal known so the DistinctRecords property no longer falls back to the empty-candidate default.

func (*RecordQueryIndexPlan) WithIndexMetadata

func (p *RecordQueryIndexPlan) WithIndexMetadata(columnNames, pkColumnNames []string, unique bool) *RecordQueryIndexPlan

WithIndexMetadata returns a shallow copy carrying the index's key columns, the record type's primary-key columns, and the UNIQUE flag. These describe the INDEX, not the scan: they are inputs to ordering derivation and to the full-equality physical-multiplicity arm of the cost model.

The names and UNIQUE bit remain derived metadata of the named index. The physical key-type vectors are different: they govern probe multiplicity and ordering congruence, so structuralKey folds them into plan identity. If a caller replaces the PK name coordinate system, any old parallel type proof is cleared to Unknown rather than applied to a different name by position.

func (*RecordQueryIndexPlan) WithKeyComponentTypes

func (p *RecordQueryIndexPlan) WithKeyComponentTypes(types []values.Type) *RecordQueryIndexPlan

WithKeyComponentTypes returns a copy with authoritative physical index-key types. The vector may include unbound key suffix components needed for ordering congruence; it is never truncated to the comparison prefix.

func (*RecordQueryIndexPlan) WithOrderingKeyNamesUnavailable

func (p *RecordQueryIndexPlan) WithOrderingKeyNamesUnavailable() *RecordQueryIndexPlan

WithOrderingKeyNamesUnavailable returns a copy that retains the physical column names for row layout/costing but forbids plan-level ordering synthesis from them. Use for expression-key indexes whose semantic ordering Values are not carried on RecordQueryIndexPlan.

func (*RecordQueryIndexPlan) WithPhysicalGroupingPrefixCount

func (p *RecordQueryIndexPlan) WithPhysicalGroupingPrefixCount(count int) *RecordQueryIndexPlan

WithPhysicalGroupingPrefixCount marks the contiguous logical grouping-key prefix of a BY_GROUP aggregate index. It is carried on the underlying index plan so the aggregate wrapper can preserve candidate metadata without a second planner-side reconstruction.

func (*RecordQueryIndexPlan) WithPrimaryKeyComponentTypes

func (p *RecordQueryIndexPlan) WithPrimaryKeyComponentTypes(types []values.Type) *RecordQueryIndexPlan

WithPrimaryKeyComponentTypes returns a copy carrying authoritative physical types aligned with GetPKColumnNames. These types affect ordering only; index scan bounds remain aligned with GetKeyComponentTypes.

func (*RecordQueryIndexPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

func (*RecordQueryIndexPlan) WithScanComparisons

func (p *RecordQueryIndexPlan) WithScanComparisons(comps []*predicates.ComparisonRange) *RecordQueryIndexPlan

WithScanComparisons returns a copy of the plan with new per-column comparison ranges, preserving every other field (covering/coveringColumns/strictlySorted/ reverse/flowedType/recordTypes). Used by the RFC-153 buried-merge correlation rebase to rewrite a SARG comparand without losing the index's covering metadata.

func (*RecordQueryIndexPlan) WithStrictlySorted

func (p *RecordQueryIndexPlan) WithStrictlySorted() *RecordQueryIndexPlan

WithStrictlySorted returns a shallow copy with strictlySorted=true.

func (*RecordQueryIndexPlan) WithValueColumnNames

func (p *RecordQueryIndexPlan) WithValueColumnNames(names []string) *RecordQueryIndexPlan

WithValueColumnNames returns a shallow copy carrying the covering-only (FDB VALUE part) column names. Like the other index metadata, this is a function of the index the plan names and stays out of the structural key.

type RecordQueryInsertPlan

type RecordQueryInsertPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryInsertPlan is the physical INSERT plan: consumes rows from an inner plan and writes them to the target record type. Mirrors a simplified subset of Java's `RecordQueryInsertPlan` (which extends RecordQueryAbstractDataModificationPlan).

Java's full surface includes per-record transforms, save-record behaviour flags, plan-graph rewriting hooks. The seed ports the minimal node-information needed by ImplementInsertRule:

  • inner: the source plan producing rows to insert
  • targetRecordType: the destination record type name
  • targetType: the rich Type the inserted rows must conform to

Result type matches inner — INSERT typically returns the inserted rows for cursor consumption.

Execute is NOT in the seed surface — wiring to FDBRecordStore is a follow-up shift gated on the rule chain producing these plans.

func NewRecordQueryInsertPlan

func NewRecordQueryInsertPlan(inner RecordQueryPlan, targetRecordType string, targetType values.Type) (*RecordQueryInsertPlan, error)

NewRecordQueryInsertPlan constructs the INSERT plan.

func NewRecordQueryInsertPlanFromQuantifier

func NewRecordQueryInsertPlanFromQuantifier(innerQ expressions.Quantifier, targetRecordType string, targetType values.Type) (*RecordQueryInsertPlan, error)

NewRecordQueryInsertPlanFromQuantifier builds an INSERT whose child is a LIVE memo quantifier (the implementation rule passes ForEachQuantifier(MemoizeExpression(winner))) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / GetResultValue all resolve through the one live edge (RFC-184 W2).

func (*RecordQueryInsertPlan) EqualsPlanWithoutChildren

func (p *RecordQueryInsertPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares targetRecordType + targetType.

func (*RecordQueryInsertPlan) EqualsWithoutChildren

func (p *RecordQueryInsertPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryInsertPlan) Explain

func (p *RecordQueryInsertPlan) Explain() string

Explain renders Insert(target, inner).

func (*RecordQueryInsertPlan) GetChildren

func (p *RecordQueryInsertPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryInsertPlan) GetInner

func (p *RecordQueryInsertPlan) GetInner() RecordQueryPlan

GetInner returns the source plan, dereferenced through the quantifier.

func (*RecordQueryInsertPlan) GetQuantifiers

func (p *RecordQueryInsertPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryInsertPlan) GetRecordQueryPlan

func (p *RecordQueryInsertPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryInsertPlan) GetResultType

func (p *RecordQueryInsertPlan) GetResultType() values.Type

GetResultType returns the inner's result type — INSERT typically returns the inserted rows for cursor consumption.

func (*RecordQueryInsertPlan) GetResultValue

func (p *RecordQueryInsertPlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the live child quantifier — INSERT passes its inner's rows through, so the result identity is the inner's, the value physicalInsertWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryInsertPlan) GetTargetRecordType

func (p *RecordQueryInsertPlan) GetTargetRecordType() string

GetTargetRecordType returns the destination record-type name.

func (*RecordQueryInsertPlan) GetTargetType

func (p *RecordQueryInsertPlan) GetTargetType() values.Type

GetTargetType returns the rich Type the inserted rows must conform to.

func (*RecordQueryInsertPlan) HashCodeWithoutChildren

func (p *RecordQueryInsertPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes class + targetRecordType.

func (*RecordQueryInsertPlan) HintCost

HintCost: one write per consumed row.

func (*RecordQueryInsertPlan) ProvenCardinalities

func (p *RecordQueryInsertPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: one effect per consumed row.

func (*RecordQueryInsertPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the plan carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the target and type, and GetInner re-resolves through the new singleton reference. This replaces physicalInsertWrapper.WithChildren (RFC-184 W2).

func (*RecordQueryInsertPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryIntersectionPlan

type RecordQueryIntersectionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryIntersectionPlan emits the bag-intersection of its inner plans — rows that appear in EVERY inner stream, compared by the comparison-key columns. Mirrors Java's `RecordQueryIntersectionPlan`.

Go's physical form is an ordered N-way intersection. Semantic, directional comparison-key parts determine the merge direction, while executable comparison values determine row equality. Unsupported ordered-bytes key shapes fail closed at construction time.

All inners must produce row-compatible streams (planner's responsibility); the comparison-key columns are matched against each row to determine intersection membership.

The legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `inners []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2.

func NewRecordQueryIntersectionPlan

func NewRecordQueryIntersectionPlan(inners []RecordQueryPlan, comparisonKeyValues []values.Value) (*RecordQueryIntersectionPlan, error)

NewRecordQueryIntersectionPlan constructs an N-way intersection. `comparisonKeyValues` defines the row-equality key (typically the primary-key columns of the result type). This compatibility constructor builds the historical forward, naturally-ascending contract; directional producers use NewRecordQueryIntersectionPlanWithOrdering.

func NewRecordQueryIntersectionPlanFromQuantifiers

func NewRecordQueryIntersectionPlanFromQuantifiers(qs []expressions.Quantifier, comparisonKeyValues []values.Value) (*RecordQueryIntersectionPlan, error)

NewRecordQueryIntersectionPlanFromQuantifiers builds an N-way intersection whose legs are LIVE memo quantifiers (the implementation / data-access rules pass ForEachQuantifiers over the freshly-memoized leg winners) instead of snapshots over plans. This makes the intersection its own cascades expression carrying its leg edges directly — the memo holds it without a physical wrapper (RFC-184 W2). comparisonKeyValues carries over verbatim.

func NewRecordQueryIntersectionPlanFromQuantifiersWithOrdering

func NewRecordQueryIntersectionPlanFromQuantifiersWithOrdering(
	qs []expressions.Quantifier,
	comparisonKeyOrderingParts []properties.ProvidedOrderingPart,
	reverse bool,
) (*RecordQueryIntersectionPlan, error)

NewRecordQueryIntersectionPlanFromQuantifiersWithOrdering is the live-memo counterpart of NewRecordQueryIntersectionPlanWithOrdering. A nil result is the same fail-closed ordered-byte optimization miss.

func NewRecordQueryIntersectionPlanFromQuantifiersWithOrderingAndSource

func NewRecordQueryIntersectionPlanFromQuantifiersWithOrderingAndSource(
	qs []expressions.Quantifier,
	comparisonKeyOrderingParts []properties.ProvidedOrderingPart,
	reverse bool,
	comparisonKeySource values.QuantifiedObjectValue,
) (*RecordQueryIntersectionPlan, error)

NewRecordQueryIntersectionPlanFromQuantifiersWithOrderingAndSource is the exact-carrier constructor used when the ordering proof declares one physical current-row phase for every comparison key. The source handle is authority: only top-level fields rooted at that exact QOV are moved onto the intersection's provided-output carrier. A same-shaped current QOV minted by another layout is not interchangeable and fails construction.

func NewRecordQueryIntersectionPlanWithOrdering

func NewRecordQueryIntersectionPlanWithOrdering(
	inners []RecordQueryPlan,
	comparisonKeyOrderingParts []properties.ProvidedOrderingPart,
	reverse bool,
) (*RecordQueryIntersectionPlan, error)

NewRecordQueryIntersectionPlanWithOrdering constructs an intersection from its semantic comparison ordering. The executable comparison Values are derived from those parts so the two contracts cannot disagree. A nil result means at least one part requires ToOrderedBytesValue evaluation, which Go does not support yet; callers must treat that as an optimization miss.

func (*RecordQueryIntersectionPlan) ChildrenAsSet

func (p *RecordQueryIntersectionPlan) ChildrenAsSet() bool

ChildrenAsSet reports that the legs of this set operation are commutative.

func (*RecordQueryIntersectionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryIntersectionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryIntersectionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryIntersectionPlan) Explain

func (p *RecordQueryIntersectionPlan) Explain() string

Explain renders Intersection(inner1, inner2, ...), appending REVERSE only for descending plans so the existing forward corpus remains byte-identical.

func (*RecordQueryIntersectionPlan) GetChildren

func (p *RecordQueryIntersectionPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plans.

func (*RecordQueryIntersectionPlan) GetComparisonKeyOrderingParts

func (p *RecordQueryIntersectionPlan) GetComparisonKeyOrderingParts() []properties.ProvidedOrderingPart

GetComparisonKeyOrderingParts returns the semantic output ordering used to derive the executable comparison key (read-only).

func (*RecordQueryIntersectionPlan) GetComparisonKeyValues

func (p *RecordQueryIntersectionPlan) GetComparisonKeyValues() []values.Value

GetComparisonKeyValues returns the row-equality key list (read-only).

func (*RecordQueryIntersectionPlan) GetInners

GetInners returns the intersection's inner plans, dereferenced through the quantifiers and in leg order.

func (*RecordQueryIntersectionPlan) GetQuantifiers

func (p *RecordQueryIntersectionPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real leg quantifiers, overriding PlanExprBase's none.

func (*RecordQueryIntersectionPlan) GetRecordQueryPlan

func (p *RecordQueryIntersectionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryIntersectionPlan) GetResultType

func (p *RecordQueryIntersectionPlan) GetResultType() values.Type

GetResultType returns the first inner's result type, or UnknownType if there are no inners.

func (*RecordQueryIntersectionPlan) GetResultValue

func (p *RecordQueryIntersectionPlan) GetResultValue() values.Value

GetResultValue returns the first leg's flowed object value — intersection emits rows compatible with all legs. Adopted from the retired physicalIntersectionWrapper (RFC-184 W2); an empty intersection falls back to PlanExprBase's fresh stand-in.

func (*RecordQueryIntersectionPlan) HashCodeWithoutChildren

func (p *RecordQueryIntersectionPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren folds the type discriminator + the comparison-key Values (semantic hashes — see writeValueHash), pairing with the semantic key equality above so equal⟹same-hash holds.

func (*RecordQueryIntersectionPlan) HintCost

HintCost: output bounded by the smallest leg.

func (*RecordQueryIntersectionPlan) HintOrdering

HintOrdering: an intersection emits rows in its semantic comparison-key order. Use the ordering parts rather than the executable comparison Values: a future mixed/counterflow key may be physically encoded as ordered bytes, but the SQL-visible ordering remains over the original columns.

func (*RecordQueryIntersectionPlan) IsIntersection

func (p *RecordQueryIntersectionPlan) IsIntersection()

IsIntersection implements properties.IntersectionExpression — the marker ComparisonsProperty.EvaluateComparisons keys on to intersect (not union) its children's comparison sets. Adopted from the retired physicalIntersectionWrapper (RFC-184 W2) so the memo member the property walks still reports it.

func (*RecordQueryIntersectionPlan) IsReverse

func (p *RecordQueryIntersectionPlan) IsReverse() bool

IsReverse reports whether the merge compares descending physical keys.

func (*RecordQueryIntersectionPlan) ProvenCardinalities

ProvenCardinalities: an intersection is bounded by its smallest leg, and can be empty whenever two legs are independently bounded.

func (*RecordQueryIntersectionPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The intersection carries its legs as LIVE memo edges, so the relink is a quantifier swap: WithQuantifiers rebinds the legs and GetInners re-resolves through the new references (RFC-184 W2, replacing physicalIntersectionWrapper.WithChildren).

func (*RecordQueryIntersectionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

type RecordQueryLimitPlan

type RecordQueryLimitPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryLimitPlan caps the result row count and optionally skips rows from an inner plan. Mirrors Java's fetch/limit plan operators.

limitValue is an OPTIONAL runtime row cap: when non-nil the executor evaluates it against the bound parameters at execution time and uses the result as the cap, ignoring the static `limit` field. It exists so a distance-ordered vector scan can be bounded by a PARAMETERIZED QUALIFY rank (`ROW_NUMBER() OVER (ORDER BY distance(...)) <= ?`): the K is unknown at plan time, so the cap must be carried as a Value (RFC-156). For a runtime limit the static `limit` is set to the no-cap sentinel (-1) so it is never mistaken for a literal LIMIT 0; the no-op-limit elimination / limit-merge rules decline on a non-nil limitValue rather than reading the sentinel.

func NewRecordQueryLimitPlan

func NewRecordQueryLimitPlan(inner RecordQueryPlan, limit, offset int64) (*RecordQueryLimitPlan, error)

func NewRecordQueryLimitPlanFromQuantifier

func NewRecordQueryLimitPlanFromQuantifier(innerQ expressions.Quantifier, limit, offset int64, limitValue values.Value) (*RecordQueryLimitPlan, error)

NewRecordQueryLimitPlanFromQuantifier builds a LIMIT whose child is a LIVE memo quantifier (the implementation rule passes ForEachQuantifier(MemoizeExpression(winner))) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetQuantifiers / OrderingSourceRef / GetInner all resolve through the one live edge. limitValue is the optional runtime cap (nil for a static literal LIMIT); when non-nil the caller passes limit=-1, the no-cap sentinel, exactly as NewRecordQueryLimitPlanWithValue does.

func NewRecordQueryLimitPlanWithValue

func NewRecordQueryLimitPlanWithValue(inner RecordQueryPlan, limitValue values.Value, offset int64) (*RecordQueryLimitPlan, error)

NewRecordQueryLimitPlanWithValue builds a LIMIT whose row cap is a runtime Value, evaluated at execution against the bound parameters. The static limit is the no-cap sentinel (-1); only limitValue is consulted.

func (*RecordQueryLimitPlan) EqualsPlanWithoutChildren

func (p *RecordQueryLimitPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryLimitPlan) EqualsWithoutChildren

func (p *RecordQueryLimitPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryLimitPlan) Explain

func (p *RecordQueryLimitPlan) Explain() string

func (*RecordQueryLimitPlan) GetChildren

func (p *RecordQueryLimitPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryLimitPlan) GetInner

func (p *RecordQueryLimitPlan) GetInner() RecordQueryPlan

GetInner exposes the single child so generic single-inner walkers (deriveColumnsFromPlan, findScanPlan, findIndexPlan, …) can descend through the limit — it is a row-count cap, transparent to column derivation and ordering. Without this the LIMIT plan, when it sits at the root (RFC-128 made the top-level LIMIT a real operator), is opaque to column derivation and the result columns resolve wrong.

func (*RecordQueryLimitPlan) GetLimit

func (p *RecordQueryLimitPlan) GetLimit() int64

func (*RecordQueryLimitPlan) GetLimitValue

func (p *RecordQueryLimitPlan) GetLimitValue() values.Value

GetLimitValue returns the optional runtime row-cap Value (nil for a static literal LIMIT).

func (*RecordQueryLimitPlan) GetOffset

func (p *RecordQueryLimitPlan) GetOffset() int64

func (*RecordQueryLimitPlan) GetQuantifiers

func (p *RecordQueryLimitPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryLimitPlan) GetRecordQueryPlan

func (p *RecordQueryLimitPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryLimitPlan) GetResultType

func (p *RecordQueryLimitPlan) GetResultType() values.Type

func (*RecordQueryLimitPlan) HashCodeWithoutChildren

func (p *RecordQueryLimitPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryLimitPlan) HintCost

HintCost: a plan-time LIMIT caps the child's cardinality. A runtime cap (GetLimitValue != nil) is unknown at plan time — leave the child cardinality unreduced (conservative) rather than reading the -1 sentinel as "no rows".

func (*RecordQueryLimitPlan) HintOrdering

func (p *RecordQueryLimitPlan) HintOrdering() properties.Ordering

HintOrdering: a limit truncates a stream without reordering it.

func (*RecordQueryLimitPlan) OrderingSourceRef

func (p *RecordQueryLimitPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryLimitPlan) ProvenCardinalities

func (p *RecordQueryLimitPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: a plan-time LIMIT caps the child's maximum.

LIMIT 0 produces exactly zero rows — not "no cap". Folding it into the negative ("no limit") arm would mis-bound any parent over a LIMIT-0 subtree as the full child cardinality.

A negative limit is no cap (an OFFSET-only stream). A RUNTIME-Value limit is also stored as limit=-1 and DELIBERATELY lands there: its real cap is only known at execution, so reading it as conservative no-cap is the sound choice — over-estimation never enables an unsound rewrite, matching the explicit HintCost conservative choice. Do not "fix" this into reducing to -1.

func (*RecordQueryLimitPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface, also consulted by pinOrderedSpine to bake the ordering-delegation spine). Because the LIMIT carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the static and runtime cap (limit / offset / limitValue), and GetInner re-resolves the plan through the new singleton reference. This replaces physicalLimitWrapper.WithChildren, whose separate snapshot `plan` field forced a WithInner rebuild to keep the cap — a single child edge needs none.

func (*RecordQueryLimitPlan) WithInner

WithInner returns a shallow copy bound to a new inner plan, preserving the cap (static or runtime). Used when an implementation rule rebuilds the wrapper around a folded leaf so the runtime limitValue is never dropped.

func (*RecordQueryLimitPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryLoadByKeysPlan

type RecordQueryLoadByKeysPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryLoadByKeysPlan returns records whose primary keys are taken from a KeysSource. This is a leaf plan (no children). Mirrors Java's RecordQueryLoadByKeysPlan.

func NewRecordQueryLoadByKeysPlan

func NewRecordQueryLoadByKeysPlan(keysSource KeysSource, flowedType values.Type) (*RecordQueryLoadByKeysPlan, error)

NewRecordQueryLoadByKeysPlan constructs the plan from a KeysSource.

func NewRecordQueryLoadByKeysPlanFromKeys

func NewRecordQueryLoadByKeysPlanFromKeys(primaryKeys []tuple.Tuple, flowedType values.Type) (*RecordQueryLoadByKeysPlan, error)

NewRecordQueryLoadByKeysPlanFromKeys constructs the plan from an explicit list of primary key tuples.

func NewRecordQueryLoadByKeysPlanFromParameter

func NewRecordQueryLoadByKeysPlanFromParameter(parameter string, flowedType values.Type) (*RecordQueryLoadByKeysPlan, error)

NewRecordQueryLoadByKeysPlanFromParameter constructs the plan from a named parameter.

func (*RecordQueryLoadByKeysPlan) EqualsPlanWithoutChildren

func (p *RecordQueryLoadByKeysPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares the key sources.

func (*RecordQueryLoadByKeysPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryLoadByKeysPlan) Explain

func (p *RecordQueryLoadByKeysPlan) Explain() string

Explain renders LoadByKeys(source).

func (*RecordQueryLoadByKeysPlan) GetChildren

func (p *RecordQueryLoadByKeysPlan) GetChildren() []RecordQueryPlan

GetChildren returns nil — this is a leaf plan.

func (*RecordQueryLoadByKeysPlan) GetKeysSource

func (p *RecordQueryLoadByKeysPlan) GetKeysSource() KeysSource

GetKeysSource returns the key source.

func (*RecordQueryLoadByKeysPlan) GetRecordQueryPlan

func (p *RecordQueryLoadByKeysPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryLoadByKeysPlan) GetResultType

func (p *RecordQueryLoadByKeysPlan) GetResultType() values.Type

func (*RecordQueryLoadByKeysPlan) HashCodeWithoutChildren

func (p *RecordQueryLoadByKeysPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes the type discriminator + key source string representation.

func (*RecordQueryLoadByKeysPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryMapPlan

type RecordQueryMapPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryMapPlan applies a transformation value to each row produced by an inner plan. Mirrors Java's `RecordQueryMapPlan`.

The resultValue defines the output shape — its Type() becomes the plan's result type, and at execution time each inner row is fed through the value's Evaluate to produce the output row.

func NewRecordQueryMapPlan

func NewRecordQueryMapPlan(inner RecordQueryPlan, resultValue values.Value) (*RecordQueryMapPlan, error)

NewRecordQueryMapPlan constructs a map plan over the given inner plan and result value.

func NewRecordQueryMapPlanFromQuantifier

func NewRecordQueryMapPlanFromQuantifier(innerQ expressions.Quantifier, resultValue values.Value) (*RecordQueryMapPlan, error)

NewRecordQueryMapPlanFromQuantifier builds a map whose child is a LIVE memo quantifier (the implementation rule passes a ForEachQuantifier over the freshly-memoized inner) instead of a snapshot over a single plan. This makes the map its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / OrderingSourceRef / GetResultValue all resolve through the one live edge (RFC-184 W2). resultValue is the PROJECTION (a RecordConstructor over the projection list), unchanged from NewRecordQueryMapPlan.

func (*RecordQueryMapPlan) EqualsPlanWithoutChildren

func (p *RecordQueryMapPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryMapPlan) EqualsWithoutChildren

func (p *RecordQueryMapPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryMapPlan) Explain

func (p *RecordQueryMapPlan) Explain() string

Explain renders Map(inner, result).

func (*RecordQueryMapPlan) GetChildren

func (p *RecordQueryMapPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryMapPlan) GetInner

func (p *RecordQueryMapPlan) GetInner() RecordQueryPlan

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryMapPlan) GetInnerQuantifier

func (p *RecordQueryMapPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the map ranges over. The PushMapThroughFetch rule matches a physical map in the memo and needs its inner GROUP (GetRangesOver) and alias to re-plan around it; since RFC-184 W2 the memo holds the bare plan (no physicalMapWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryMapPlan) GetQuantifiers

func (p *RecordQueryMapPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryMapPlan) GetRecordQueryPlan

func (p *RecordQueryMapPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryMapPlan) GetResultType

func (p *RecordQueryMapPlan) GetResultType() values.Type

GetResultType returns the result value's type.

func (*RecordQueryMapPlan) GetResultValue

func (p *RecordQueryMapPlan) GetResultValue() values.Value

GetResultValue returns the transformation value.

func (*RecordQueryMapPlan) HashCodeWithoutChildren

func (p *RecordQueryMapPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryMapPlan) HintCost

HintCost: per-row projection, cardinality-preserving.

func (*RecordQueryMapPlan) HintOrdering

func (p *RecordQueryMapPlan) HintOrdering() properties.Ordering

HintOrdering: a map reshapes rows without reordering them.

func (*RecordQueryMapPlan) OrderingSourceRef

func (p *RecordQueryMapPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryMapPlan) ProvenCardinalities

func (p *RecordQueryMapPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: per-row projection is 1:1.

func (*RecordQueryMapPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the map carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the projection result value, and GetInner re-resolves through the new singleton reference. This replaces physicalMapWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild gated on isLeafReplaceable — a single live child edge needs neither the snapshot nor the gate (extraction resolves the child group to its winner and hands it back through this swap).

func (*RecordQueryMapPlan) WithInner

WithInner returns a copy with the inner replaced and every other field preserved — the extraction-relink rebuild path (see findPhysicalPlan's shell completion). A constructor rebuild would drop fields the setters carry, so identity-preserving copy is the only safe form.

func (*RecordQueryMapPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryMergeSortUnionPlan

type RecordQueryMergeSortUnionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryMergeSortUnionPlan is the ordered (merge-sorted) union variant. Children must produce rows sorted by the comparison keys; the plan merges them maintaining that order. Optionally deduplicates rows that have equal comparison keys.

Mirrors Java's RecordQueryUnionOnValuesPlan for comparison-key values, reverse direction, and the deduplicating mode. Go additionally supports removeDuplicates=false for ordered UNION ALL; Java's RecordQueryUnionPlan always uses the deduplicating UnionCursor.

The legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `inners []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2.

func NewRecordQueryMergeSortUnionPlan

func NewRecordQueryMergeSortUnionPlan(
	inners []RecordQueryPlan,
	comparisonKeys []values.Value,
	reverse bool,
	removeDuplicates bool,
) (*RecordQueryMergeSortUnionPlan, error)

func NewRecordQueryMergeSortUnionPlanFromQuantifiers

func NewRecordQueryMergeSortUnionPlanFromQuantifiers(
	qs []expressions.Quantifier,
	comparisonKeys []values.Value,
	reverse bool,
	removeDuplicates bool,
) (*RecordQueryMergeSortUnionPlan, error)

NewRecordQueryMergeSortUnionPlanFromQuantifiers builds an ordered merge-sort union whose legs are LIVE memo quantifiers (the distinct-union rule passes PhysicalQuantifiers over the freshly-pinned leg winners) instead of snapshots over plans. This makes the merge its own cascades expression carrying its leg edges directly — the memo holds it without a physical wrapper (RFC-184 W2). The comparison keys, reverse, and dedup flags carry over verbatim.

func (*RecordQueryMergeSortUnionPlan) ChildrenAsSet

func (p *RecordQueryMergeSortUnionPlan) ChildrenAsSet() bool

ChildrenAsSet reports that the legs of this set operation are commutative.

func (*RecordQueryMergeSortUnionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryMergeSortUnionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryMergeSortUnionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryMergeSortUnionPlan) Explain

func (*RecordQueryMergeSortUnionPlan) GetChildren

func (*RecordQueryMergeSortUnionPlan) GetComparisonKeys

func (p *RecordQueryMergeSortUnionPlan) GetComparisonKeys() []values.Value

func (*RecordQueryMergeSortUnionPlan) GetInners

GetInners returns the legs, dereferenced through the quantifiers and in merge order — which the merge itself depends on.

func (*RecordQueryMergeSortUnionPlan) GetQuantifiers

GetQuantifiers reports the real leg quantifiers, overriding PlanExprBase's none.

func (*RecordQueryMergeSortUnionPlan) GetRecordQueryPlan

func (p *RecordQueryMergeSortUnionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryMergeSortUnionPlan) GetResultType

func (p *RecordQueryMergeSortUnionPlan) GetResultType() values.Type

func (*RecordQueryMergeSortUnionPlan) GetResultValue

func (p *RecordQueryMergeSortUnionPlan) GetResultValue() values.Value

GetResultValue returns the first leg's flowed object value — the merge emits rows compatible with all legs. Adopted from the retired physicalMergeSortUnionWrapper (RFC-184 W2); an empty union falls back to PlanExprBase's fresh stand-in.

func (*RecordQueryMergeSortUnionPlan) HashCodeWithoutChildren

func (p *RecordQueryMergeSortUnionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryMergeSortUnionPlan) HintCost

HintCost: every leg is scanned and merged.

func (*RecordQueryMergeSortUnionPlan) HintOrdering

HintOrdering: a merge-sort union emits rows in its comparison-key order, in the direction it merges. See RecordQueryInUnionPlan.HintOrdering for why the single reverse flag is the whole truth about that direction.

func (*RecordQueryMergeSortUnionPlan) IsReverse

func (p *RecordQueryMergeSortUnionPlan) IsReverse() bool

func (*RecordQueryMergeSortUnionPlan) ProvenCardinalities

ProvenCardinalities: a union concatenates its legs — bounds sum.

func (*RecordQueryMergeSortUnionPlan) RemovesDuplicates

func (p *RecordQueryMergeSortUnionPlan) RemovesDuplicates() bool

func (*RecordQueryMergeSortUnionPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The merge carries its legs as LIVE memo edges, so the relink is a quantifier swap: WithQuantifiers rebinds the legs and GetInners re-resolves through the new references (RFC-184 W2, replacing physicalMergeSortUnionWrapper.WithChildren).

func (*RecordQueryMergeSortUnionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

type RecordQueryMultiIntersectionOnValuesPlan

type RecordQueryMultiIntersectionOnValuesPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryMultiIntersectionOnValuesPlan merges N input streams where all streams are ordered by the same comparison key (grouping columns). For each group of rows where the comparison key matches across ALL streams, it produces one output row combining:

  • Common values (grouping columns) — taken from any stream (they're identical)
  • Pick-up values (aggregates) — one from each stream

Mirrors Java's RecordQueryMultiIntersectionOnValuesPlan which extends RecordQueryIntersectionPlan and adds a resultValue that constructs the merged output row from quantifier bindings.

The children are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `children []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2.

func NewRecordQueryMultiIntersectionOnValuesPlan

func NewRecordQueryMultiIntersectionOnValuesPlan(
	children []RecordQueryPlan,
	comparisonKey []values.Value,
	resultValue values.Value,
) (*RecordQueryMultiIntersectionOnValuesPlan, error)

NewRecordQueryMultiIntersectionOnValuesPlan constructs an N-way multi-intersection. comparisonKey defines the row-equality key (grouping columns); resultValue is the Value expression that constructs the output row from quantifier bindings.

func NewRecordQueryMultiIntersectionOnValuesPlanFromQuantifiers

func NewRecordQueryMultiIntersectionOnValuesPlanFromQuantifiers(
	qs []expressions.Quantifier,
	comparisonKey []values.Value,
	resultValue values.Value,
) (*RecordQueryMultiIntersectionOnValuesPlan, error)

NewRecordQueryMultiIntersectionOnValuesPlanFromQuantifiers builds an N-way multi-intersection whose streams are LIVE memo quantifiers (the aggregate data-access rule passes PhysicalQuantifiers over the freshly-memoized leg plans) instead of snapshots over plans. This makes the multi-intersection its own cascades expression carrying its stream edges directly — the memo holds it without a physical wrapper (RFC-184 W2). comparisonKey and resultValue carry over verbatim.

func (*RecordQueryMultiIntersectionOnValuesPlan) DrivingStreamIndex

func (p *RecordQueryMultiIntersectionOnValuesPlan) DrivingStreamIndex() int

DrivingStreamIndex resolves the driving alias to a position in stream order, or -1 when this plan is an inner intersection.

A non-zero alias that names no stream returns -1 too, and every caller treats -1 as "not an outer merge". That is deliberate: an unresolvable designation must not silently degrade to "drive from stream 0".

func (*RecordQueryMultiIntersectionOnValuesPlan) EqualsPlanWithoutChildren

func (p *RecordQueryMultiIntersectionOnValuesPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryMultiIntersectionOnValuesPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryMultiIntersectionOnValuesPlan) Explain

Explain renders MultiIntersection(child1, child2, ...; keys=[...]).

func (*RecordQueryMultiIntersectionOnValuesPlan) GetChildren

GetChildren returns the input plans, dereferenced through the quantifiers and in stream order — resultValue's pick-up columns are positional per stream.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetComparisonKey

func (p *RecordQueryMultiIntersectionOnValuesPlan) GetComparisonKey() []values.Value

GetComparisonKey returns the grouping-column values used to match rows across all input streams.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetDrivingAlias

GetDrivingAlias returns the group-existence stream's alias, or the zero value when this is a plain inner intersection.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetQuantifiers

GetQuantifiers reports the real child quantifiers, overriding PlanExprBase's none. These are also what GetResultValue's nil-fallback reads.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetRecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetResultType

GetResultType returns the result Value's type if a resultValue is set, or UnknownType otherwise.

func (*RecordQueryMultiIntersectionOnValuesPlan) GetResultValue

GetResultValue returns the Value expression that constructs the merged output row, falling back to the FIRST stream's flowed object value when this plan carries none.

The fallback is physicalMultiIntersectionWrapper's, adopted here now that the plan owns its child quantifiers: the wrapper answered innerQuants[0].GetFlowedObjectValue() because the plan had no quantifiers of its own to ask. It does now, so the wrapper holds no information the plan lacks and becomes deletable.

The final arm defers to PlanExprBase rather than repeating its fresh stand-in, so a 0-stream plan answers exactly what every other plan answers.

func (*RecordQueryMultiIntersectionOnValuesPlan) HasDrivingAlias

func (p *RecordQueryMultiIntersectionOnValuesPlan) HasDrivingAlias() bool

HasDrivingAlias reports whether a driving stream was DESIGNATED, regardless of whether it still resolves. The executor uses this to tell "inner intersection" (nothing designated) from "outer merge whose designation was lost" (designated but unresolvable) — the latter must fail loudly, never run as an intersection.

func (*RecordQueryMultiIntersectionOnValuesPlan) HashCodeWithoutChildren

func (p *RecordQueryMultiIntersectionOnValuesPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren folds the type discriminator, comparison key values, and result value (semantic Value hashes — see writeValueHash).

func (*RecordQueryMultiIntersectionOnValuesPlan) HintCost

HintCost: output bounded by the smallest leg. With no child costs yet (an un-costed memo probe) fall back to a group-cardinality estimate over the declared leg count.

func (*RecordQueryMultiIntersectionOnValuesPlan) HintOrdering

HintOrdering: a multi-way intersection emits rows in its comparison-key order, when it has one.

func (*RecordQueryMultiIntersectionOnValuesPlan) IsIntersection

func (p *RecordQueryMultiIntersectionOnValuesPlan) IsIntersection()

IsIntersection implements properties.IntersectionExpression — the marker ComparisonsProperty.EvaluateComparisons keys on to intersect (not union) its children's comparison sets. Adopted from the retired physicalMultiIntersectionWrapper (RFC-184 W2) so the memo member the property walks still reports it.

func (*RecordQueryMultiIntersectionOnValuesPlan) IsOuter

IsOuter reports whether this merge has a resolvable driving stream.

func (*RecordQueryMultiIntersectionOnValuesPlan) ProvenCardinalities

ProvenCardinalities: an intersection is bounded by its smallest leg, and can be empty whenever two legs are independently bounded.

func (*RecordQueryMultiIntersectionOnValuesPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The multi-intersection carries its streams as LIVE memo edges, so the relink rebuilds the streams and every retained Value program before GetChildren re-resolves through the new references (RFC-184 W2, replacing physicalMultiIntersectionWrapper.WithChildren).

func (*RecordQueryMultiIntersectionOnValuesPlan) WithDrivingStream

WithDrivingStream returns a copy of this plan whose merge is OUTER, driven by the stream carried by the given quantifier alias (RFC-209 §5.3(b)).

The alias must belong to one of this plan's streams. A plan whose driving alias resolves to nothing is not executable as an outer merge — the executor refuses it rather than silently running an intersection, which is the fail-closed property §5.3 asks for.

func (*RecordQueryMultiIntersectionOnValuesPlan) WithQuantifiers

WithQuantifiers atomically rebuilds the merge over the replacement child edges. Comparison keys and the result constructor may retain any of those edge aliases, so all positional old→new pairs participate in one checked rebase before PlanExprBase is reconstructed.

The arity check matters more here than for a plain set operation: resultValue picks up one aggregate per stream by position, so a different-length child list would not describe the same row.

type RecordQueryNestedLoopJoinPlan

type RecordQueryNestedLoopJoinPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryNestedLoopJoinPlan represents a nested-loop join of two child plans. For each row in the outer (left) plan, the inner (right) plan is evaluated and the join predicate is applied to the combined row. This is the simplest and most general join strategy — it handles all join types (inner, left, cross) without requiring ordered input.

Mirrors Java's `com.apple.foundationdb.record.query.plan.plans.RecordQueryFlatMapPlan` which is the underlying implementation of nested-loop joins in the Record Layer.

The two legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQueryFlatMapPlan`'s outer/inner `Quantifier.Physical`). The raw `outer`/`inner` pointers they replace were a second storage location for the same edges. They stay two separately-named fields rather than a slice because the accessors and the join predicates address them by ROLE — the outer is the driving side — not by position. RFC-183 P5 step 2.

func NewRecordQueryNestedLoopJoinPlan

func NewRecordQueryNestedLoopJoinPlan(
	outer, inner RecordQueryPlan,
	joinPredicates []predicates.QueryPredicate,
	joinType JoinType,
	outerAlias, innerAlias values.CorrelationIdentifier,
	resultValue values.Value,
) (*RecordQueryNestedLoopJoinPlan, error)

NewRecordQueryNestedLoopJoinPlan constructs a nested-loop join plan. outerAlias/innerAlias identify the two legs of the merged row this join emits: the executor qualifies merged-row keys by them and stamps them onto the row's leg boundaries, so they are what an alias-qualified column reference resolves through.

They are CorrelationIdentifiers, not strings, because that is what they identify — a quantifier — and because the executor's leg boundaries compare them through values.SameLeg. Holding them as text meant the executor minted an identifier from a string at the plan boundary, and an exact comparison cannot protect against a forgery its own mint constructs: the mint decides the spelling, so the case-disjointness that keeps a quoted "Q$5" from binding a planner-minted q$5 was being re-decided at every consumer. Java holds the same thing typed end to end (RecordQueryFlatMapPlan carries Quantifier.Physical, not an alias string), and Go's own RecordQueryFlatMapPlan already did.

func NewRecordQueryNestedLoopJoinPlanFromQuantifiers

func NewRecordQueryNestedLoopJoinPlanFromQuantifiers(
	outerQ, innerQ expressions.Quantifier,
	joinPredicates []predicates.QueryPredicate,
	joinType JoinType,
	outerAlias, innerAlias values.CorrelationIdentifier,
	resultValue values.Value,
) (*RecordQueryNestedLoopJoinPlan, error)

NewRecordQueryNestedLoopJoinPlanFromQuantifiers builds a nested-loop join whose two legs are supplied memo quantifiers instead of snapshots over concrete plans. This makes the plan its own cascades expression carrying its child edges directly — the memo holds it without a physicalNestedLoopJoinWrapper (RFC-184 W2). The materialized NLJ is uncorrelated (CanCorrelate=false), so both legs carry the LIVE shared-group edge the emitter memoized; the join predicates, join type, table aliases and result value are preserved so EqualsPlanWithoutChildren / GetCorrelatedToWithoutChildren stay identical.

func (*RecordQueryNestedLoopJoinPlan) EqualsPlanWithoutChildren

func (p *RecordQueryNestedLoopJoinPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryNestedLoopJoinPlan) EqualsWithoutChildren

func (p *RecordQueryNestedLoopJoinPlan) EqualsWithoutChildren(other expressions.RelationalExpression, aliases *expressions.AliasMap) bool

EqualsWithoutChildren compares child-local aliases, predicates, the result program and its physical output layout through the memo's alpha-renaming.

func (*RecordQueryNestedLoopJoinPlan) Explain

func (*RecordQueryNestedLoopJoinPlan) GetChildren

GetChildren returns the outer leg then the inner leg, dereferenced through the quantifiers. The pair is always two entries wide — a nil leg stays a nil entry rather than shrinking the arity.

func (*RecordQueryNestedLoopJoinPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryNestedLoopJoinPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren walks this plan's own predicates, mirroring physicalNestedLoopJoinWrapper. The predicates are this node's information — a correlation reached only through them would be invisible to correlation-driven rules if this returned the empty default.

func (*RecordQueryNestedLoopJoinPlan) GetInner

func (*RecordQueryNestedLoopJoinPlan) GetInnerAlias

func (*RecordQueryNestedLoopJoinPlan) GetJoinType

func (p *RecordQueryNestedLoopJoinPlan) GetJoinType() JoinType

func (*RecordQueryNestedLoopJoinPlan) GetOuter

func (*RecordQueryNestedLoopJoinPlan) GetOuterAlias

func (*RecordQueryNestedLoopJoinPlan) GetPredicates

func (*RecordQueryNestedLoopJoinPlan) GetQuantifiers

GetQuantifiers reports the real leg quantifiers in GetChildren order (outer, inner), overriding PlanExprBase's none. That order is what WithQuantifiers indexes into.

func (*RecordQueryNestedLoopJoinPlan) GetRecordQueryPlan

func (p *RecordQueryNestedLoopJoinPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryNestedLoopJoinPlan) GetResultType

func (p *RecordQueryNestedLoopJoinPlan) GetResultType() values.Type

func (*RecordQueryNestedLoopJoinPlan) GetResultValue

func (p *RecordQueryNestedLoopJoinPlan) GetResultValue() values.Value

func (*RecordQueryNestedLoopJoinPlan) HashCodeWithoutChildren

func (p *RecordQueryNestedLoopJoinPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren folds the structural discriminators. Predicates fold predicates.SemanticHashCode (alias-invariant, coarser than the structural PredicateEquals — equal⟹same-hash holds), NOT Explain() display text, which is for humans and carries no identity contract. The resultValue joins identity — the Java counterpart (RecordQueryFlatMapPlan) compares via semanticEqualsForResults; two joins differing only in the combined-row shape they emit are not interchangeable.

func (*RecordQueryNestedLoopJoinPlan) HintCost

HintCost: a MATERIALIZED nested-loop join — the inner is executed once. When p's own join predicates PROVABLY bind the inner leg's full UNIQUE key via equality (nestedLoopJoinUniqueKeyConjuncts), NestedLoopJoinCost applies the derived 1/innerCard selectivity for those conjuncts instead of the flat FilterSelectivity guess — see that function's and NestedLoopJoinCost's doc comments for why the flat guess is wrong there (a ~500x overestimate for a 1000-row inner) and disagrees with the SAME logical join's FlatMap-shape cost, which the total-preorder join-ordering comparison (RFC-192) requires to agree.

func (*RecordQueryNestedLoopJoinPlan) HintOrdering

HintOrdering: a nested-loop join's output order is not modeled.

func (*RecordQueryNestedLoopJoinPlan) ProvenCardinalities

ProvenCardinalities: outer x inner, matching the FlatMap shape of the same logical join — the two physical realizations of one logical join must prove the same bound, or the clamp would price them differently for reasons that are not about cost.

func (*RecordQueryNestedLoopJoinPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The join carries its two legs as memo quantifiers, so the relink is a positional quantifier swap: WithQuantifiers copies the receiver (preserving the predicates, join type, table aliases and result value) and re-resolves GetOuter/GetInner through the new references. This replaces physicalNestedLoopJoinWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field held the yield-time children verbatim; the swap re-resolves to the memo winner instead.

func (*RecordQueryNestedLoopJoinPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers, in GetQuantifiers order. The receiver is never mutated, which is what keeps a memoized plan safe to share.

type RecordQueryPlan

type RecordQueryPlan interface {
	// A plan IS a RelationalExpression — Java's
	// `QueryPlan<T> extends PlanHashable, RelationalExpression`
	// (QueryPlan.java:51), inherited by RecordQueryPlan
	// (RecordQueryPlan.java:73). Embedding it here is the Go spelling of
	// that `extends`, and it is what lets a plan be a memo member and hold
	// its child as a Quantifier instead of a raw pointer.
	//
	// Note this supplies HashCodeWithoutChildren, which both interfaces
	// declare with the same signature.
	expressions.RelationalExpression

	// GetResultType returns the rich Type of rows this plan emits.
	// Always a RelationType.
	GetResultType() values.Type

	// ProvidedOutputLayout returns the immutable physical ordinal layout of
	// every row this plan emits. A concrete layout returns (layout, nil). A
	// valid dynamic carrier returns a typed OrdinalLayoutUnavailableError with
	// OrdinalLayoutDynamicCarrier; every other nil layout returns the
	// OrdinalLayoutMalformedPlan code. There is no nil,nil or unknown-layout
	// state.
	ProvidedOutputLayout() (values.OrdinalLayout, error)

	// OrdinalPhysicalProperties returns this plan's immutable required input,
	// evaluation-program, and provided output layout view. It fails with the
	// same typed availability error as ProvidedOutputLayout when an exact
	// physical carrier has not yet been selected or construction was bypassed.
	OrdinalPhysicalProperties() (OrdinalPhysicalProperties, error)

	// GetChildren returns this plan's input plans, in stable order.
	// Read-only; callers must not mutate.
	GetChildren() []RecordQueryPlan

	// EqualsPlanWithoutChildren reports whether this plan's node-
	// information matches `other`'s. Children are not consulted —
	// caller's job (typically by recursing into GetChildren).
	EqualsPlanWithoutChildren(other RecordQueryPlan) bool

	// HashCodeWithoutChildren returns the structural hash of this
	// node's node-information. Must be consistent with
	// EqualsPlanWithoutChildren: x.Equals(y) implies x.Hash() == y.Hash().
	HashCodeWithoutChildren() uint64

	// Explain returns a single-line human-readable label for this
	// plan node. Implementations should match Java's
	// `Plan.toString()` shape where reasonable.
	Explain() string
}

RecordQueryPlan is the root interface for every physical plan node. Mirrors Java's `RecordQueryPlan` interface — implementations produce a record stream when executed against an FDBRecordStore.

The seed exposes node-information accessors (GetResultType, GetChildren, EqualsPlanWithoutChildren, HashCodeWithoutChildren) and an Explain method for diagnostic rendering. Execute is NOT in the seed surface — wiring to FDBRecordStore is a follow-up shift gated on the rule chain being able to produce these plans end-to-end.

type RecordQueryPredicatesFilterPlan

type RecordQueryPredicatesFilterPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryPredicatesFilterPlan applies a list of QueryPredicates to an inner plan's row stream. Mirrors Java's `RecordQueryPredicatesFilterPlan`.

Unlike RecordQueryFilterPlan (which also takes QueryPredicates), this variant is produced by ImplementSimpleSelectRule and models the Cascades-era predicate-filter operator that works with the richer predicate hierarchy (ValuePredicate, ExistentialValuePredicate, etc.) rather than the legacy comparison-based filter.

func NewRecordQueryPredicatesFilterPlan

func NewRecordQueryPredicatesFilterPlan(inner RecordQueryPlan, preds []predicates.QueryPredicate) (*RecordQueryPredicatesFilterPlan, error)

NewRecordQueryPredicatesFilterPlan constructs a predicates filter over the given inner plan and predicate list.

func NewRecordQueryPredicatesFilterPlanFromQuantifier

func NewRecordQueryPredicatesFilterPlanFromQuantifier(innerQ expressions.Quantifier, preds []predicates.QueryPredicate) (*RecordQueryPredicatesFilterPlan, error)

NewRecordQueryPredicatesFilterPlanFromQuantifier builds a predicates filter whose child is a supplied memo quantifier instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly — the memo holds it without a physicalPredicatesFilterWrapper (RFC-184 W2).

The emitter freezes a DISENTANGLED FINAL reference holding the filter's concrete inner member (constraint-preserving disentangle), so planFromQuantifier resolves that concrete member — never the shared-group winner. The predicate list is preserved.

func NewRecordQueryPredicatesFilterPlanWithAlias

func NewRecordQueryPredicatesFilterPlanWithAlias(inner RecordQueryPlan, preds []predicates.QueryPredicate, alias values.CorrelationIdentifier) (*RecordQueryPredicatesFilterPlan, error)

NewRecordQueryPredicatesFilterPlanWithAlias constructs a predicates filter that binds the current row as a correlation under innerAlias before evaluating predicates. Mirrors Java's evalFilter which calls context.withBinding(CORRELATION, getInner().getAlias(), queryResult).

func NewRecordQueryPredicatesFilterPlanWithAliasFromQuantifier

func NewRecordQueryPredicatesFilterPlanWithAliasFromQuantifier(innerQ expressions.Quantifier, preds []predicates.QueryPredicate, alias values.CorrelationIdentifier) (*RecordQueryPredicatesFilterPlan, error)

NewRecordQueryPredicatesFilterPlanWithAliasFromQuantifier is the binding-alias form of NewRecordQueryPredicatesFilterPlanFromQuantifier. It preserves BOTH the predicate list AND the innerAlias the current row is bound under during predicate evaluation.

func (*RecordQueryPredicatesFilterPlan) EqualsPlanWithoutChildren

func (p *RecordQueryPredicatesFilterPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryPredicatesFilterPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryPredicatesFilterPlan) Explain

Explain renders PredicatesFilter(inner, [pred1, pred2, ...]).

func (*RecordQueryPredicatesFilterPlan) GetChildren

GetChildren returns the inner plan as the only child.

func (*RecordQueryPredicatesFilterPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryPredicatesFilterPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren walks this plan's own predicates, mirroring physicalPredicatesFilterWrapper. The predicates are this node's information — a correlation reached only through them would be invisible to correlation-driven rules if this returned the empty default.

func (*RecordQueryPredicatesFilterPlan) GetInner

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryPredicatesFilterPlan) GetInnerAlias

GetInnerAlias returns the correlation alias under which the current row is bound during predicate evaluation. Zero value means no binding.

func (*RecordQueryPredicatesFilterPlan) GetInnerQuantifier

func (p *RecordQueryPredicatesFilterPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the filter ranges over. derivationsForPredicatesFilter reads its alias to translate the predicates' correlations; since RFC-184 W2 the memo holds the bare plan (no physicalPredicatesFilterWrapper whose innerQuant field it used to read), this exposes the same edge.

func (*RecordQueryPredicatesFilterPlan) GetPredicates

GetPredicates returns the predicate list (read-only).

func (*RecordQueryPredicatesFilterPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryPredicatesFilterPlan) GetRecordQueryPlan

func (p *RecordQueryPredicatesFilterPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryPredicatesFilterPlan) GetResultType

func (p *RecordQueryPredicatesFilterPlan) GetResultType() values.Type

GetResultType returns the inner's result type (filter doesn't reshape rows).

func (*RecordQueryPredicatesFilterPlan) GetResultValue

func (p *RecordQueryPredicatesFilterPlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the child quantifier — a filter passes its input's rows through unchanged, so its row identity IS the inner's. This is the identity physicalPredicatesFilterWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryPredicatesFilterPlan) HashCodeWithoutChildren

func (p *RecordQueryPredicatesFilterPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes the class discriminator + per-predicate predicates.SemanticHashCode (alias-invariant, coarser than the structural PredicateEquals — equal⟹same-hash holds by construction). NOT Explain() display text: renderings are for humans, carry no identity contract, and drift independently of equality.

func (*RecordQueryPredicatesFilterPlan) HintCost

HintCost: same formula as RecordQueryFilterPlan.HintCost — one selectivity factor per CONJUNCT (predicates.CountConjuncts, not len()), so the same logical residual costs identically whether it reaches this plan as `[a, b]` or as `[And(a, b)]`. Previously duplicated FilterCost's body inline while counting via len(); now delegates so there is exactly one formula to keep in sync with NestedLoopJoinCost's numPreds.

func (*RecordQueryPredicatesFilterPlan) HintOrdering

HintOrdering: a filter preserves its input's order.

func (*RecordQueryPredicatesFilterPlan) OrderingSourceRef

func (p *RecordQueryPredicatesFilterPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryPredicatesFilterPlan) ProvenCardinalities

ProvenCardinalities: a filter may eliminate every row, so the minimum drops to zero; the maximum is inherited.

func (*RecordQueryPredicatesFilterPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The filter carries its child as a single frozen memo edge, so the relink checked-rebases child-edge predicate Values while preserving the distinct logical binding alias, and GetInner re-resolves through the new singleton reference. This replaces physicalPredicatesFilterWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild gated on isLeafReplaceable. Because the emitter already froze the concrete inner into a private single-member reference, extraction recurses through it faithfully — it never consults a shared exploratory group, so a correlated inner is preserved.

func (*RecordQueryPredicatesFilterPlan) WithInner

WithInner returns a copy with the inner replaced and every other field preserved — the extraction-relink rebuild path (see findPhysicalPlan's shell completion). A constructor rebuild would drop fields the setters carry, so identity-preserving copy is the only safe form.

func (*RecordQueryPredicatesFilterPlan) WithQuantifiers

WithQuantifiers atomically moves every predicate Value that belongs to the physical child edge onto the replacement edge, then reconstructs the pass-through base. innerAlias is a distinct logical binding identity and is preserved; correlations rooted there (or in outer scopes) are deliberately absent from the old-edge alias map and remain unchanged.

type RecordQueryProjectionPlan

type RecordQueryProjectionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryProjectionPlan applies a projection (column selection / expression evaluation) over an inner plan's row stream. Mirrors Java's conceptual projection in RecordQueryFetchFromPartialRecordPlan / the MapPipelinedCursor mechanics. The seed models it as a distinct plan node for clarity.

func NewRecordQueryProjectionPlan

func NewRecordQueryProjectionPlan(projections []values.Value, inner RecordQueryPlan) (*RecordQueryProjectionPlan, error)

func NewRecordQueryProjectionPlanFromQuantifier

func NewRecordQueryProjectionPlanFromQuantifier(projections []values.Value, aliases []string, innerQ expressions.Quantifier) (*RecordQueryProjectionPlan, error)

NewRecordQueryProjectionPlanFromQuantifier builds the projection directly over the LIVE inner memo edge the implement rule already memoized, rather than snapshotting a bare plan. The plan is then its own cascades expression carrying the child edge once — no wrapper storing a second copy (RFC-184 W2).

func NewRecordQueryProjectionPlanFromQuantifierWithOutputSchema

func NewRecordQueryProjectionPlanFromQuantifierWithOutputSchema(
	projections []values.Value,
	aliases []string,
	aliasMinted []bool,
	outputNames []string,
	innerQ expressions.Quantifier,
) (*RecordQueryProjectionPlan, error)

NewRecordQueryProjectionPlanFromQuantifierWithOutputSchema preserves the exact logical result schema while rebased Values address the selected physical edge. outputNames must be the logical projection's frozen, deduplicated names in slot order.

func NewRecordQueryProjectionPlanFromQuantifierWithProvenance

func NewRecordQueryProjectionPlanFromQuantifierWithProvenance(projections []values.Value, aliases []string, aliasMinted []bool, innerQ expressions.Quantifier) (*RecordQueryProjectionPlan, error)

NewRecordQueryProjectionPlanFromQuantifierWithProvenance is NewRecordQueryProjectionPlanFromQuantifier plus the per-slot record of who named each output. Every lowering of a logical projection goes through here so the provenance survives the logical→physical boundary; the plain constructor stays for machinery that has no aliases to explain.

func NewRecordQueryProjectionPlanWithAliases

func NewRecordQueryProjectionPlanWithAliases(projections []values.Value, aliases []string, inner RecordQueryPlan) (*RecordQueryProjectionPlan, error)

func NewRecordQueryProjectionPlanWithOutputSchema

func NewRecordQueryProjectionPlanWithOutputSchema(
	projections []values.Value,
	aliases []string,
	aliasMinted []bool,
	outputNames []string,
	inner RecordQueryPlan,
) (*RecordQueryProjectionPlan, error)

NewRecordQueryProjectionPlanWithOutputSchema rebuilds a projection over a concrete child while preserving the output schema and alias provenance that were established before its Value program was rebased.

func (*RecordQueryProjectionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryProjectionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryProjectionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryProjectionPlan) Explain

func (p *RecordQueryProjectionPlan) Explain() string

func (*RecordQueryProjectionPlan) GetAliasMinted

func (p *RecordQueryProjectionPlan) GetAliasMinted() []bool

GetAliasMinted returns the per-slot alias provenance, parallel to GetAliases: true = machinery-minted datum key, false (and every slot past the slice) = the user's `AS`.

func (*RecordQueryProjectionPlan) GetAliasSources

GetAliasSources returns a defensive copy of the frozen structured source identities for machinery-minted aliases. A short/nil vector is uncaptured, never permission to reconstruct a source from alias text.

func (*RecordQueryProjectionPlan) GetAliases

func (p *RecordQueryProjectionPlan) GetAliases() []string

func (*RecordQueryProjectionPlan) GetChildren

func (p *RecordQueryProjectionPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryProjectionPlan) GetDistinctProofIndexName

func (p *RecordQueryProjectionPlan) GetDistinctProofIndexName() string

GetDistinctProofIndexName implements DistinctProofStamped.

func (*RecordQueryProjectionPlan) GetInner

func (*RecordQueryProjectionPlan) GetInnerQuantifier

func (p *RecordQueryProjectionPlan) GetInnerQuantifier() expressions.Quantifier

GetInnerQuantifier returns the live child edge — the memo quantifier the projection ranges over (RFC-184 W2).

func (*RecordQueryProjectionPlan) GetOutputNames

func (p *RecordQueryProjectionPlan) GetOutputNames() []string

func (*RecordQueryProjectionPlan) GetProjections

func (p *RecordQueryProjectionPlan) GetProjections() []values.Value

func (*RecordQueryProjectionPlan) GetQuantifiers

func (p *RecordQueryProjectionPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryProjectionPlan) GetRecordQueryPlan

func (p *RecordQueryProjectionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryProjectionPlan) GetResultType

func (p *RecordQueryProjectionPlan) GetResultType() values.Type

GetResultType derives from the result value, which is Java's arrangement: RelationalExpression.getResultType() is `Type.Relation(getResultValue() .getResultType())` and NO Java expression or plan overrides it (RelationalExpression.java:194-197). It was a hardcoded UnknownType, which made every consumer re-derive the row by name — the supply side RFC-226 removes.

func (*RecordQueryProjectionPlan) GetResultValue

func (p *RecordQueryProjectionPlan) GetResultValue() values.Value

GetResultValue states the row this projection PRODUCES — the same derivation its logical twin uses (values.ProjectionResultValue), so the two cannot drift.

It must be stated here rather than inherited: PlanExprBase.GetResultValue mints a QOV over a FRESH unique correlation, which no consumer can resolve against this plan's columns.

This is also what the executor emits. executeProjection builds a PositionalRow with exactly one slot per projection, named by values.OutputColumnName — the authority ProjectionResultValue also uses — so the row stated here and the row emitted there are the same row.

func (*RecordQueryProjectionPlan) HashCodeWithoutChildren

func (p *RecordQueryProjectionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryProjectionPlan) HintCost

HintCost: projection is cardinality-preserving with a per-row CPU charge.

func (*RecordQueryProjectionPlan) HintOrdering

func (p *RecordQueryProjectionPlan) HintOrdering() properties.Ordering

HintOrdering: a projection reshapes rows without reordering them.

func (*RecordQueryProjectionPlan) IsIdentity

func (p *RecordQueryProjectionPlan) IsIdentity() bool

IsIdentity returns true if this projection passes all columns through unchanged: it has no schema-changing output alias and its sole QuantifiedObjectValue references this projection's inner quantifier. An identity projection can be removed without changing either rows or schema.

func (*RecordQueryProjectionPlan) OrderingSourceRef

func (p *RecordQueryProjectionPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryProjectionPlan) ProvenCardinalities

ProvenCardinalities: projection is cardinality-preserving.

func (*RecordQueryProjectionPlan) TieBreakHashCodeWithoutChildren

func (p *RecordQueryProjectionPlan) TieBreakHashCodeWithoutChildren() uint64

TieBreakHashCodeWithoutChildren returns the projection's schema-neutral historical structural hash for deterministic candidate ranking. Memo equality/hashing remains schema-aware through structuralKey.

func (*RecordQueryProjectionPlan) WithAliasProvenance

func (p *RecordQueryProjectionPlan) WithAliasProvenance(aliasMinted []bool) *RecordQueryProjectionPlan

WithAliasProvenance returns a copy carrying the given per-slot alias provenance. It is the rebase/rebuild path's carry-across: a rewrite that hands back "the same projection, moved" must preserve who named each slot.

func (*RecordQueryProjectionPlan) WithAliasSources

WithAliasSources returns a copy carrying checked structured alias-source provenance. The source is intentionally metadata-only and does not enter structural identity or hashing.

func (*RecordQueryProjectionPlan) WithChildren

WithChildren rebuilds over a fresh inner quantifier — the optional interface plan extraction uses to preserve the strict-singleton invariant. The fresh child edge has a fresh correlation, so WithQuantifiers also checked-rebases every retained projection onto that exact edge before rebuilding the result Value and admitted physical properties.

func (*RecordQueryProjectionPlan) WithDistinctProofIndexName

func (p *RecordQueryProjectionPlan) WithDistinctProofIndexName(indexName string) RecordQueryPlan

WithDistinctProofIndexName implements DistinctProofStampable.

func (*RecordQueryProjectionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryRecursiveDfsJoinPlan

type RecordQueryRecursiveDfsJoinPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryRecursiveDfsJoinPlan implements a recursive depth-first join: the root plan seeds the traversal, and the child plan is re-evaluated for each row using priorCorrelation to bind the "prior" row. Mirrors Java's `com.apple.foundationdb.record.query.plan.plans.RecordQueryRecursiveDfsJoinPlan`.

The two legs are stored ONCE, as Quantifiers over References — Java's shape (`Quantifier.Physical` for the root and the recursive child). The raw `root`/`child` pointers they replace were a second storage location for the same edges. They stay two separately-named fields rather than a slice because the legs are not interchangeable: the root seeds the traversal and the child is re-evaluated per row against priorCorrelation. RFC-183 P5 step 2.

func NewRecordQueryRecursiveDfsJoinPlan

func NewRecordQueryRecursiveDfsJoinPlan(
	root, child RecordQueryPlan,
	priorCorrelation values.CorrelationIdentifier,
	strategy DfsTraversalStrategy,
) (*RecordQueryRecursiveDfsJoinPlan, error)

func NewRecordQueryRecursiveDfsJoinPlanDistinct

func NewRecordQueryRecursiveDfsJoinPlanDistinct(
	root, child RecordQueryPlan,
	priorCorrelation values.CorrelationIdentifier,
	strategy DfsTraversalStrategy,
) (*RecordQueryRecursiveDfsJoinPlan, error)

NewRecordQueryRecursiveDfsJoinPlanDistinct creates a DFS plan with UNION DISTINCT deduplication.

func NewRecordQueryRecursiveDfsJoinPlanFromQuantifiers

func NewRecordQueryRecursiveDfsJoinPlanFromQuantifiers(
	rootQ, childQ expressions.Quantifier,
	priorCorrelation values.CorrelationIdentifier,
	strategy DfsTraversalStrategy,
	distinct bool,
) (*RecordQueryRecursiveDfsJoinPlan, error)

NewRecordQueryRecursiveDfsJoinPlanFromQuantifiers builds a recursive DFS join whose two legs are LIVE memo quantifiers (the implementation rule passes ForEachQuantifiers over the freshly-memoized root/child scan expressions) instead of snapshots over plans. This makes the plan its own cascades expression carrying its leg edges directly — the memo holds it without a physical wrapper (RFC-184 W2). The prior-row correlation, traversal strategy, and distinct flag carry over verbatim.

func (*RecordQueryRecursiveDfsJoinPlan) CanCorrelate

func (p *RecordQueryRecursiveDfsJoinPlan) CanCorrelate() bool

CanCorrelate reports that this operator anchors a correlation between its children (the seed leg binds what the recursive leg reads).

func (*RecordQueryRecursiveDfsJoinPlan) EqualsPlanWithoutChildren

func (p *RecordQueryRecursiveDfsJoinPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryRecursiveDfsJoinPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryRecursiveDfsJoinPlan) Explain

func (*RecordQueryRecursiveDfsJoinPlan) GetChild

func (*RecordQueryRecursiveDfsJoinPlan) GetChildren

GetChildren returns the root leg then the recursive child leg, dereferenced through the quantifiers. The pair is always two entries wide — a nil leg stays a nil entry rather than shrinking the arity.

func (*RecordQueryRecursiveDfsJoinPlan) GetPriorCorrelation

func (*RecordQueryRecursiveDfsJoinPlan) GetQuantifiers

GetQuantifiers reports the real leg quantifiers in GetChildren order (root, child), overriding PlanExprBase's none. That order is what WithQuantifiers indexes into.

func (*RecordQueryRecursiveDfsJoinPlan) GetRecordQueryPlan

func (p *RecordQueryRecursiveDfsJoinPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryRecursiveDfsJoinPlan) GetResultType

func (p *RecordQueryRecursiveDfsJoinPlan) GetResultType() values.Type

func (*RecordQueryRecursiveDfsJoinPlan) GetRoot

func (*RecordQueryRecursiveDfsJoinPlan) GetTraversalStrategy

func (p *RecordQueryRecursiveDfsJoinPlan) GetTraversalStrategy() DfsTraversalStrategy

func (*RecordQueryRecursiveDfsJoinPlan) HashCodeWithoutChildren

func (p *RecordQueryRecursiveDfsJoinPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryRecursiveDfsJoinPlan) HintCost

HintCost: depth-first recursive traversal from each root row. The DFS cursor streams one root→leaf path with a charge-once-per-depth stack (see levelUnionBufferTouches), so it carries no level-buffer term.

func (*RecordQueryRecursiveDfsJoinPlan) HintOrdering

HintOrdering: recursive traversal order is not modeled.

func (*RecordQueryRecursiveDfsJoinPlan) IsDistinct

func (p *RecordQueryRecursiveDfsJoinPlan) IsDistinct() bool

func (*RecordQueryRecursiveDfsJoinPlan) ProvenCardinalities

ProvenCardinalities: the traversal emits every ROOT row (plus whatever descendants it finds), so the minimum is the root leg's; the depth is data, so the maximum is unknown. Identical to the level union's bound, because the two are physical realizations of ONE logical operator and cannot prove different row counts for the same recursion.

JAVA DIVERGENCE, deliberate and in the sound direction. Java's PLAN-level visitRecordQueryRecursiveDfsJoinPlan returns unknownMaxCardinality (min 0), while Java's own LOGICAL visitRecursiveUnionExpression proves {initialState.min, unknown} for the same operator — so Java's two arms disagree, and the plan arm is the loose one. Go follows the logical arm.

Verified sound against Go's executor rather than assumed: recursive_cursor.go pushes each root node with emitPending set (:247), so every root row is emitted; UNION DISTINCT deduplication can only collapse duplicates, and a set built from at least one row still holds at least one row.

The floor holds for BOTH traversal strategies, which the emitPending flag alone does not show. PREORDER emits on the way down (:168, gated on c.preorder); POSTORDER never takes that branch, and its rows come out of the POP path instead (:203-210), which drains any node still flagged emitPending as the walk unwinds — the same flag, consumed at the other end. A continuation-restored node re-arms it precisely for that case (`emitPending = !c.preorder`, :240): in preorder it was already emitted before its children on the prior page and must not repeat, in postorder it still owes its emission. So no root row is dropped under DfsPostorder, and the bound is not a preorder-only argument.

Leaving it at Java's looser answer is not cosmetic. Measured on identical children, a LIMIT-0 recursive leg gives FlatMap(scan, dfsJoin) Cardinality 0 against FlatMap(scan, levelUnion) 1e6 — so RFC-195's headline zero-collapse survived on the DFS alternative, which is the one the cost model PREFERS (the level union carries a strictly larger buffer term by construction). The clamp cannot floor what the proof does not claim.

func (*RecordQueryRecursiveDfsJoinPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The plan carries its root and recursive legs as LIVE memo edges, so the relink is a quantifier swap: WithQuantifiers rebinds the legs and GetChildren re-resolves through the new references (RFC-184 W2, replacing physicalRecursiveDfsJoinWrapper.WithChildren).

func (*RecordQueryRecursiveDfsJoinPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers, in GetQuantifiers order. The receiver is never mutated, which is what keeps a memoized plan safe to share.

type RecordQueryRecursiveLevelUnionPlan

type RecordQueryRecursiveLevelUnionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryRecursiveLevelUnionPlan implements a recursive level-order (breadth-first) union: the initial-state plan seeds the first level, and the recursive-state plan is re-evaluated for each level using two temp tables (scan/insert) that are flipped between levels. Mirrors Java's RecordQueryRecursiveLevelUnionPlan.

The two legs are stored ONCE, as Quantifiers over References — Java's shape (`Quantifier.Physical` for the initial and recursive states). The raw `initialState`/`recursiveState` pointers they replace were a second storage location for the same edges. They stay two separately-named fields rather than a slice because the legs are not interchangeable: one seeds level zero, the other is re-run per level against the flipped temp tables. RFC-183 P5 step 2.

func NewRecordQueryRecursiveLevelUnionPlan

func NewRecordQueryRecursiveLevelUnionPlan(
	initialState, recursiveState RecordQueryPlan,
	tempTableScanAlias, tempTableInsertAlias values.CorrelationIdentifier,
) (*RecordQueryRecursiveLevelUnionPlan, error)

func NewRecordQueryRecursiveLevelUnionPlanDistinct

func NewRecordQueryRecursiveLevelUnionPlanDistinct(
	initialState, recursiveState RecordQueryPlan,
	tempTableScanAlias, tempTableInsertAlias values.CorrelationIdentifier,
) (*RecordQueryRecursiveLevelUnionPlan, error)

NewRecordQueryRecursiveLevelUnionPlanDistinct creates a plan with UNION DISTINCT deduplication.

func NewRecordQueryRecursiveLevelUnionPlanFromQuantifiers

func NewRecordQueryRecursiveLevelUnionPlanFromQuantifiers(
	initialQ, recursiveQ expressions.Quantifier,
	tempTableScanAlias, tempTableInsertAlias values.CorrelationIdentifier,
	distinct bool,
) (*RecordQueryRecursiveLevelUnionPlan, error)

NewRecordQueryRecursiveLevelUnionPlanFromQuantifiers builds a recursive level union whose two legs are LIVE memo quantifiers (the implementation rule passes ForEachQuantifiers over the freshly-memoized initial/recursive winners) instead of snapshots over plans. This makes the plan its own cascades expression carrying its leg edges directly — the memo holds it without a physical wrapper (RFC-184 W2). The temp-table aliases and distinct flag carry over verbatim.

func (*RecordQueryRecursiveLevelUnionPlan) CanCorrelate

func (p *RecordQueryRecursiveLevelUnionPlan) CanCorrelate() bool

CanCorrelate matches Java's RecordQueryRecursiveLevelUnionPlan, which has NO canCorrelate override and so answers false (the default). The recursion's level-to-level binding is NOT a Cascades correlation anchored here: Java satisfies the temp-table scan/insert aliases explicitly in computeCorrelatedTo (filtered out), and the cursor (RecursiveUnionCursor) carries the per-level temp-table flip at execution — nothing in the memo binds a sibling leg's alias through this operator. Answering true would (via Reference.GetCorrelatedTo) SUPPRESS propagation of an outer alias a leg legitimately reads — a wrong-rows shape when a recursive CTE sits on the inner side of a lateral correlation and Go's human-readable alias reuse collides an outer alias with a leg's own. The sibling RecordQueryRecursiveDfsJoinPlan DOES override to true (Java parity) — the divergence is specific to the LEVEL union.

func (*RecordQueryRecursiveLevelUnionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryRecursiveLevelUnionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryRecursiveLevelUnionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryRecursiveLevelUnionPlan) Explain

func (*RecordQueryRecursiveLevelUnionPlan) GetChildren

GetChildren returns the initial-state leg then the recursive-state leg, dereferenced through the quantifiers. The pair is always two entries wide — a nil leg stays a nil entry rather than shrinking the arity.

func (*RecordQueryRecursiveLevelUnionPlan) GetInitialState

func (*RecordQueryRecursiveLevelUnionPlan) GetQuantifiers

GetQuantifiers reports the real leg quantifiers in GetChildren order (initial, recursive), overriding PlanExprBase's none. That order is what WithQuantifiers indexes into.

func (*RecordQueryRecursiveLevelUnionPlan) GetRecordQueryPlan

func (p *RecordQueryRecursiveLevelUnionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryRecursiveLevelUnionPlan) GetRecursiveState

func (p *RecordQueryRecursiveLevelUnionPlan) GetRecursiveState() RecordQueryPlan

func (*RecordQueryRecursiveLevelUnionPlan) GetResultType

func (p *RecordQueryRecursiveLevelUnionPlan) GetResultType() values.Type

func (*RecordQueryRecursiveLevelUnionPlan) GetTempTableInsertAlias

func (*RecordQueryRecursiveLevelUnionPlan) GetTempTableScanAlias

func (*RecordQueryRecursiveLevelUnionPlan) HashCodeWithoutChildren

func (p *RecordQueryRecursiveLevelUnionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryRecursiveLevelUnionPlan) HintCost

HintCost: level-at-a-time recursive union from the initial level. It costs the same base recursion as the DFS join PLUS a level-buffer echo: every materialized frontier row is written to and read back from a temp table, and the drained buffer's charge is echoed (not refunded) into the next level (see levelUnionBufferTouches). The added CPU term makes the union strictly costlier than the DFS join for identical children, so the planner prefers DFS on cost. This formula's ONE body lives on HintCostWithin (cardinality_bounds.go), because the buffer term is charged per materialized OUTPUT row and therefore has to see the CLAMPED cardinality. Delegating with an unknown interval makes the clamp a deterministic no-op, so an un-bounded caller gets exactly the pre-RFC-195 answer — and there is no second copy for a test to exercise while production runs the other one.

func (*RecordQueryRecursiveLevelUnionPlan) HintCostWithin

HintCostWithin: the level union's buffer term is charged per MATERIALIZED OUTPUT ROW, so it must be computed from the CLAMPED cardinality — this is the one formula in the planner whose CPU derives from its own output rather than from what it consumes.

Clamping the returned Cost instead would leave the buffer term computed from the disproven number: a one-row seed with a zero-estimated recursive leg pays ZERO buffer work, and the clamp then asserts the output is at least one row. That erases the level-union-vs-DFS cost distinction the buffer term exists to draw — the DFS join buffers no level at all — in the very act of fixing the cardinality. The clamp therefore runs on the interval BEFORE the term is computed, which is what keeps the emitted Cost internally consistent: no component of it is a function of a cardinality the same Cost no longer carries. It is also the ONLY body: RecordQueryRecursiveLevelUnionPlan.HintCost delegates here with an unknown interval (which makes the clamp a no-op), so there is exactly one implementation of this formula rather than two that must be kept in step. Two bodies is how a safety test comes to exercise the copy nothing calls.

func (*RecordQueryRecursiveLevelUnionPlan) HintOrdering

HintOrdering: recursive level order is not modeled.

func (*RecordQueryRecursiveLevelUnionPlan) IsDistinct

func (p *RecordQueryRecursiveLevelUnionPlan) IsDistinct() bool

func (*RecordQueryRecursiveLevelUnionPlan) ProvenCardinalities

ProvenCardinalities: UNION ALL always emits at least the seed, so the minimum is the seed leg's; the recursion depth is unbounded at plan time.

Matching Java's visitRecordQueryRecursiveLevelUnionPlan, which takes the initial state's minimum and an unknown maximum.

This minimum is the bound recursiveCost contradicted: it computes seedCard*recCard with NO additive seed term, so a recursive leg whose own estimate is exactly zero (a LIMIT 0 leg) collapses the product to zero even though the seed alone guarantees a row — and a zero propagates multiplicatively through FlatMapCost and NestedLoopJoinCost, costing an entire join subtree at zero.

func (*RecordQueryRecursiveLevelUnionPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The plan carries its two legs as LIVE memo edges, so the relink is a quantifier swap: WithQuantifiers rebinds the legs and GetChildren re-resolves through the new references (RFC-184 W2, replacing physicalRecursiveLevelUnionWrapper.WithChildren).

func (*RecordQueryRecursiveLevelUnionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers, in GetQuantifiers order. The receiver is never mutated, which is what keeps a memoized plan safe to share.

type RecordQueryScanPlan

type RecordQueryScanPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryScanPlan is a primary-key scan over a set of record types — the leaf physical-plan that reads records sequentially from the FDB store. Mirrors Java's `RecordQueryScanPlan`.

Seed surface:

  • RecordTypes: which record types to emit. Empty = all types.
  • FlowedType: the rich Type of the row stream (RecordType for a single type, UnionType for multi-type scans).
  • Reverse: whether to scan in reverse PK order.

What's NOT in the seed: range bounds, scan-property bag, continuation, scan-comparison thunk. Those land when consumers (Batch A index rules) need them.

func NewRecordQueryScanPlan

func NewRecordQueryScanPlan(recordTypes []string, flowedType values.Type, reverse bool) (*RecordQueryScanPlan, error)

NewRecordQueryScanPlan builds a scan over the given record types in the given direction. recordTypes is normalised (sorted + deduped); empty slice → scan over all types.

func (*RecordQueryScanPlan) EqualsPlanWithoutChildren

func (p *RecordQueryScanPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryScanPlan) EqualsWithoutChildren

func (p *RecordQueryScanPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryScanPlan) Explain

func (p *RecordQueryScanPlan) Explain() string

Explain renders a one-line label.

func (*RecordQueryScanPlan) GetChildren

func (p *RecordQueryScanPlan) GetChildren() []RecordQueryPlan

GetChildren returns the empty slice — scans are leaves.

func (*RecordQueryScanPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryScanPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren reports the correlations reached through this scan's comparison operands.

func (*RecordQueryScanPlan) GetDistinctProofIndexName

func (p *RecordQueryScanPlan) GetDistinctProofIndexName() string

GetDistinctProofIndexName implements DistinctProofStamped. A base-record scan is the shape the secondary-UNIQUE DISTINCT elision actually produces on the unordered `SELECT DISTINCT <unique column>` regime the optimization is for, so it must be able to carry the proof directly — the elided plan is sometimes a bare scan with no projection above it (`SELECT DISTINCT *`).

func (*RecordQueryScanPlan) GetFlowedType

func (p *RecordQueryScanPlan) GetFlowedType() values.Type

GetFlowedType returns the rich Type of rows flowing out.

func (*RecordQueryScanPlan) GetKeyComponentTypes

func (p *RecordQueryScanPlan) GetKeyComponentTypes() []values.Type

GetKeyComponentTypes returns the authoritative physical types aligned with GetScanComparisons.

func (*RecordQueryScanPlan) GetPrimaryKeyValues

func (p *RecordQueryScanPlan) GetPrimaryKeyValues() []values.Value

GetPrimaryKeyValues returns the primary key values, or nil if not set.

func (*RecordQueryScanPlan) GetRecordQueryPlan

func (p *RecordQueryScanPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

This method, present on every plan type, is what lets a bare plan stand in for a physical wrapper in the memo: cascades recognises a physical expression by asserting `RelationalExpression + GetRecordQueryPlan()` (physical_wrapper.go's physicalPlanExpression), and step 1 already gave plans the RelationalExpression half.

It is deliberately PER-TYPE rather than a method on PlanExprBase. The embedded base is a zero-size struct with no back-pointer to the value that embeds it, so a base implementation could only ever return nil or itself — never the outer plan. Go has no `self` type; each type must name itself.

func (*RecordQueryScanPlan) GetRecordTypes

func (p *RecordQueryScanPlan) GetRecordTypes() []string

GetRecordTypes returns the canonical record-type-name list.

func (*RecordQueryScanPlan) GetResultType

func (p *RecordQueryScanPlan) GetResultType() values.Type

GetResultType returns the row Type — same as FlowedType for the seed (no per-row projection in a scan).

func (*RecordQueryScanPlan) GetResultValue

func (p *RecordQueryScanPlan) GetResultValue() values.Value

GetResultValue returns the scan's STABLE per-instance result value — the single correlation identity a bare scan carries as its own memo expression (RFC-184 W2), the role a physical scan wrapper's GetResultValue used to play. Unlike PlanExprBase's method (a fresh QOV per call), this returns the same value the constructor minted, so repeated interrogations of one plan instance agree. Falls back to PlanExprBase for struct-literal test plans that bypass the constructor (resultValue is nil there).

func (*RecordQueryScanPlan) GetScanComparisons

func (p *RecordQueryScanPlan) GetScanComparisons() []*predicates.ComparisonRange

GetScanComparisons returns the per-column comparison ranges for PK narrowing.

func (*RecordQueryScanPlan) HashCodeWithoutChildren

func (p *RecordQueryScanPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryScanPlan) HintCost

HintCost: a full scan reads every record of the covered types, discounted by the bound-comparison selectivity. A fully-equality-bound scan over the primary key has an exact finite physical-key multiplicity, but only when the stamped primary-key shape proves full coverage and every equality class is statically bounded. It is usually one; each known signed-zero FLOAT/DOUBLE component doubles it, while a dynamic floating comparand fails closed.

The point-lookup branch charges FetchCPU, not ScanCPU: a full-PK equality bind is ONE isolated GetRange round trip with nothing to amortize over (see properties.FetchCPU's doc comment for the executor trace) — the same physical shape as a Fetch, not a multi-row streaming scan.

func (*RecordQueryScanPlan) HintOrdering

func (p *RecordQueryScanPlan) HintOrdering() properties.Ordering

HintOrdering: a primary scan produces rows in primary-key order.

func (*RecordQueryScanPlan) HintRichOrdering

func (p *RecordQueryScanPlan) HintRichOrdering() *properties.RichOrdering

HintRichOrdering returns a primary scan's PK ordering with bindings: PK positions bound by an equality comparison become FixedBinding entries, the rest SortedBinding. A primary scan is a value-index-like candidate in Java (PrimaryScanMatchCandidate implements ValueIndexLikeMatchCandidate), so its ordering comes from the same computeOrderingFromScanComparisons: the equality prefix is Binding.fixed, which is compatible with ANY requested direction.

func (*RecordQueryScanPlan) IsReverse

func (p *RecordQueryScanPlan) IsReverse() bool

IsReverse reports the scan direction.

func (*RecordQueryScanPlan) ProvenCardinalities

ProvenCardinalities: a full-primary-key-equality primary scan has a finite physical multiplicity when every component can be bounded. Ordinary keys prove at most one row; k known signed-zero float components prove at most 2^k rows because logical equality probes both encodings. A range, partial or dynamic floating bind stays unknown.

The proof and RecordQueryScanPlan.HintCost both run through the SAME shared physical multiplicity authority, so one plan cannot carry a cost that says "one row" and a proof that says otherwise, or the reverse. That reverse is not hypothetical: the derivation this replaces consulted a helper whose widening guard sat AFTER its stamped-primary-key early return, so a scan with a stamped PK and a terminal zero-valued FLOAT equality was PROVEN at-most-one while the cost model correctly declined to treat it as a point probe. The executor widens a zero bound across -0.0 and +0.0 (IEEE-equal, distinct adjacent keys), so that proof was false, and under RFC-195's clamp a false max=1 would have CAPPED the honest estimate to it.

func (*RecordQueryScanPlan) WithDistinctProofIndexName

func (p *RecordQueryScanPlan) WithDistinctProofIndexName(indexName string) RecordQueryPlan

WithDistinctProofIndexName implements DistinctProofStampable.

func (*RecordQueryScanPlan) WithKeyComponentTypes

func (p *RecordQueryScanPlan) WithKeyComponentTypes(types []values.Type) *RecordQueryScanPlan

WithKeyComponentTypes returns a copy carrying authoritative physical primary-key types. The vector may extend past the bound comparison prefix: ordering proofs need the domains of unbound suffix components too. Missing entries required by comparisons are made explicit as UnknownType.

func (*RecordQueryScanPlan) WithPrimaryKey

func (p *RecordQueryScanPlan) WithPrimaryKey(pk []values.Value) *RecordQueryScanPlan

WithPrimaryKey returns a copy of the scan plan with PK values set. Preserves scanComparisons (a copy must carry every scan field — dropping the comparisons here silently un-narrows the scan; production happens to set the PK before the comparisons, so the drop was latent, but the asymmetry with WithScanComparisons was a footgun).

func (*RecordQueryScanPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

func (*RecordQueryScanPlan) WithScanComparisons

func (p *RecordQueryScanPlan) WithScanComparisons(comps []*predicates.ComparisonRange) *RecordQueryScanPlan

WithScanComparisons returns a copy with the given scan comparisons. Mirrors Java's RecordQueryScanPlan constructor that accepts ScanComparisons.

type RecordQueryScoreForRankPlan

type RecordQueryScoreForRankPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryScoreForRankPlan wraps an inner plan and evaluates rank/score functions, binding the results into the evaluation context so the inner plan can use them as parameters. Mirrors Java's RecordQueryScoreForRankPlan.

This is a STRUCTURE-ONLY port — no execution logic.

func NewRecordQueryScoreForRankPlan

func NewRecordQueryScoreForRankPlan(inner RecordQueryPlan, ranks []ScoreForRank) (*RecordQueryScoreForRankPlan, error)

NewRecordQueryScoreForRankPlan constructs a score-for-rank plan.

func (*RecordQueryScoreForRankPlan) EqualsPlanWithoutChildren

func (p *RecordQueryScoreForRankPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsPlanWithoutChildren compares the ranks list.

func (*RecordQueryScoreForRankPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryScoreForRankPlan) Explain

func (p *RecordQueryScoreForRankPlan) Explain() string

Explain renders ScoreForRank([rank1, rank2], inner).

func (*RecordQueryScoreForRankPlan) GetChildren

func (p *RecordQueryScoreForRankPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryScoreForRankPlan) GetInner

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryScoreForRankPlan) GetQuantifiers

func (p *RecordQueryScoreForRankPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryScoreForRankPlan) GetRanks

func (p *RecordQueryScoreForRankPlan) GetRanks() []ScoreForRank

GetRanks returns the list of ScoreForRank entries.

func (*RecordQueryScoreForRankPlan) GetRecordQueryPlan

func (p *RecordQueryScoreForRankPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryScoreForRankPlan) GetResultType

func (p *RecordQueryScoreForRankPlan) GetResultType() values.Type

GetResultType returns the inner plan's result type (score-for-rank doesn't reshape rows — it binds scores into the evaluation context, then delegates row production to the inner plan).

func (*RecordQueryScoreForRankPlan) HashCodeWithoutChildren

func (p *RecordQueryScoreForRankPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes the class discriminator + ranks.

func (*RecordQueryScoreForRankPlan) IsReverse

func (p *RecordQueryScoreForRankPlan) IsReverse() bool

IsReverse delegates to the inner plan.

func (*RecordQueryScoreForRankPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQuerySelectorPlan

type RecordQuerySelectorPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQuerySelectorPlan selects one of its children to be executed at runtime. The selector determines which child plan to use via a PlanSelector policy. Mirrors Java's RecordQuerySelectorPlan.

The children are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `children []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2. Child ORDER is load-bearing: PlanSelector returns an index into it.

func NewRecordQuerySelectorPlan

func NewRecordQuerySelectorPlan(
	children []RecordQueryPlan,
	planSelector PlanSelector,
	reverse bool,
) (*RecordQuerySelectorPlan, error)

NewRecordQuerySelectorPlan constructs a selector plan. Returns an error if children is empty or their exact result types disagree.

func NewRecordQuerySelectorPlanWithProbabilities

func NewRecordQuerySelectorPlanWithProbabilities(
	children []RecordQueryPlan,
	probabilities []int,
	reverse bool,
) (*RecordQuerySelectorPlan, error)

NewRecordQuerySelectorPlanWithProbabilities constructs a selector plan using relative probabilities. Panics if the list lengths differ or children is empty.

func (*RecordQuerySelectorPlan) EqualsPlanWithoutChildren

func (p *RecordQuerySelectorPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares reverse flag and plan selector.

func (*RecordQuerySelectorPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQuerySelectorPlan) Explain

func (p *RecordQuerySelectorPlan) Explain() string

Explain renders Selector(child1, child2, ..., selector).

func (*RecordQuerySelectorPlan) GetChildren

func (p *RecordQuerySelectorPlan) GetChildren() []RecordQueryPlan

GetChildren returns the child plans, dereferenced through the quantifiers and in the order PlanSelector's index refers to.

func (*RecordQuerySelectorPlan) GetPlanSelector

func (p *RecordQuerySelectorPlan) GetPlanSelector() PlanSelector

GetPlanSelector returns the plan selector.

func (*RecordQuerySelectorPlan) GetQuantifiers

func (p *RecordQuerySelectorPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifiers, overriding PlanExprBase's none.

func (*RecordQuerySelectorPlan) GetRecordQueryPlan

func (p *RecordQuerySelectorPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQuerySelectorPlan) GetResultType

func (p *RecordQuerySelectorPlan) GetResultType() values.Type

GetResultType returns the type of the plan's result value. There is no childless case to answer for: the constructor rejects an empty child list.

func (*RecordQuerySelectorPlan) HashCodeWithoutChildren

func (p *RecordQuerySelectorPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes reverse flag and plan selector label.

func (*RecordQuerySelectorPlan) IsReverse

func (p *RecordQuerySelectorPlan) IsReverse() bool

IsReverse reports the scan direction.

func (*RecordQuerySelectorPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

The arity check keeps the PlanSelector's index meaningful: a probability list is sized to the child count at construction, so only a same-length replacement is admissible.

type RecordQueryStreamingAggregationPlan

type RecordQueryStreamingAggregationPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryStreamingAggregationPlan groups input rows by grouping keys and computes aggregates over each group in a streaming fashion. The plan requires that the inner plan produces rows already sorted by the grouping keys — no materialisation needed.

Mirrors Java's RecordQueryStreamingAggregationPlan: the streaming operator reads sorted input and emits one output row per change in the grouping-key combination. When the inner is NOT ordered by grouping keys, ImplementStreamingAggregationRule does not fire — a sort is needed first, or the hash-aggregate path (future) is used instead.

func NewRecordQueryStreamingAggregationPlan

func NewRecordQueryStreamingAggregationPlan(
	inner RecordQueryPlan,
	groupingKeys []values.Value,
	aggregates []expressions.AggregateSpec,
) (*RecordQueryStreamingAggregationPlan, error)

func NewRecordQueryStreamingAggregationPlanFromQuantifier

func NewRecordQueryStreamingAggregationPlanFromQuantifier(
	innerQ expressions.Quantifier,
	groupingKeys []values.Value,
	aggregates []expressions.AggregateSpec,
) (*RecordQueryStreamingAggregationPlan, error)

NewRecordQueryStreamingAggregationPlanFromQuantifier builds a streaming aggregation whose child is a supplied memo quantifier instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly — the memo holds it without a physicalStreamingAggWrapper (RFC-184 W2).

Streaming aggregation is a PRODUCER, not an ordering-delegator: it reshapes rows (one output row per grouping-key change) and provides its OWN output ordering. But it has a CORRECTNESS PRECONDITION — the inner must be ordered by the grouping keys — so the emitter chooses the child edge per arm: a plain count-only aggregation (no grouping keys) or a self-contained ordered producer (an InMemorySort it builds, a covering index scan) carries the LIVE shared-group edge, while a DELEGATING ordered inner (an existing Fetch/Filter spine) is frozen deep by pinOrderedSpine + FinalOf so it cannot float to an unordered sibling and split groups. The grouping keys and aggregate specs are preserved so OutputRecordType / GetResultValue stay stable.

func (*RecordQueryStreamingAggregationPlan) EqualsPlanWithoutChildren

func (p *RecordQueryStreamingAggregationPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryStreamingAggregationPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryStreamingAggregationPlan) Explain

func (*RecordQueryStreamingAggregationPlan) GetAggregates

func (*RecordQueryStreamingAggregationPlan) GetChildren

func (*RecordQueryStreamingAggregationPlan) GetGroupingKeys

func (p *RecordQueryStreamingAggregationPlan) GetGroupingKeys() []values.Value

func (*RecordQueryStreamingAggregationPlan) GetInner

func (*RecordQueryStreamingAggregationPlan) GetInnerQuantifier

GetInnerQuantifier returns the live child quantifier — the single memo edge the aggregation ranges over. Since RFC-184 W2 the memo holds the bare plan (no physicalStreamingAggWrapper whose innerQuant field was read), this exposes the same edge for derivations and extraction.

func (*RecordQueryStreamingAggregationPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryStreamingAggregationPlan) GetRecordQueryPlan

func (p *RecordQueryStreamingAggregationPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryStreamingAggregationPlan) GetResultType

func (p *RecordQueryStreamingAggregationPlan) GetResultType() values.Type

func (*RecordQueryStreamingAggregationPlan) GetResultValue

func (p *RecordQueryStreamingAggregationPlan) GetResultValue() values.Value

GetResultValue flows a TYPED QOV whose RecordType is the aggregate's output schema ([groupKeys, aggregates], the plan's single naming authority), so the resolver BAKES downstream references to ordinals at plan time (Java's getFieldNameToOrdinalMap). A downstream ref then reads the aggregateCursor's PositionalRow by Get(ordinal) — order, not spelling — robust to redundant spellings of the same column. A streaming aggregation is a PRODUCER: it does NOT flow its inner's rows through, so this must NOT delegate to the child's flowed value (unlike the filter/distinct passthroughs). This is the identity physicalStreamingAggWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryStreamingAggregationPlan) HashCodeWithoutChildren

func (p *RecordQueryStreamingAggregationPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryStreamingAggregationPlan) HintCost

HintCost: grouped aggregation emits one row per group.

func (*RecordQueryStreamingAggregationPlan) HintOrdering

HintOrdering: the advertised ordering is over the aggregate's OUTPUT row — group key i flows as output column i, NAMED by the canonical group-key output name (AggregateKeyColumnName, the same authority the runtime output row and the ORDER-BY-over-aggregate bake use). Advertising the raw grouping-key VALUES (input-relative bakes over the pre-aggregate row) mis-rendered the provided keys and made a satisfied ORDER BY look unsatisfied — a spurious second InMemorySort above the aggregate; an evaluating consumer (a merge comparison key) would also have read the aggregate's output row with a dead pre-aggregate ordinal. A grouping key that TERMINATES the ordering claim truncates it here exactly as it does on an index scan, and for the same reason: a streaming aggregation emits its groups in the order its input hands them over, so a FLOAT/DOUBLE grouping key means the groups come out in tuple-key order, with a negative-NaN group physically FIRST and logically LAST.

The truncation is asked of the same authority the scan producers ask (values.TypeTerminatesOrderingClaim, via claimableKeyLimit) because the grouping keys are Values that already carry their declared type. This plan does NOT inherit the decision from its inner: StreamingAggFromIndexRule builds it by matching grouping keys against index column NAMES and never reads the inner's ordering claim at all, so terminating the inner scan's claim does not reach this producer.

func (*RecordQueryStreamingAggregationPlan) OutputColumnNames

func (p *RecordQueryStreamingAggregationPlan) OutputColumnNames() []string

OutputColumnNames is the SINGLE naming authority for this plan's output row: grouping keys (in GROUP BY order) then aggregates (in aggregate order), each alias-preferring. The ordinal model bakes downstream references against this order, and the executor's aggregateCursor emits its PositionalRow with these exact names — so a reference over the aggregate resolves by Get(ordinal) (Java's getFieldValueForFieldOrdinals) instead of a spelling-sensitive name lookup.

func (*RecordQueryStreamingAggregationPlan) OutputRecordType

func (p *RecordQueryStreamingAggregationPlan) OutputRecordType() *values.RecordType

OutputRecordType is OutputColumnNames as a RAW RecordType (ordinal == slice position; dup-name-safe). Flowed as the aggregate's result-value QOV type so the resolver BAKES downstream references to ordinals at plan time.

func (*RecordQueryStreamingAggregationPlan) ProvenCardinalities

ProvenCardinalities: an UNGROUPED streaming aggregation applies its aggregates over the entire child result set and emits a single row — at most one, structurally. A grouped aggregation's group count is data, not structure.

This max=1 is the bound the cost model contradicted by five orders of magnitude: the hint charges in*DistinctSelectivity with no cap, which for a 1e6-row child is ~700,000 rows for an operator that provably emits one, so every join ordering above it was computed against a number wrong by 700,000x.

func (*RecordQueryStreamingAggregationPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). The aggregation carries its child as a single memo edge, so the relink is an atomic child/program rebuild: WithQuantifiers checked-rebases the grouping keys and aggregate operands before re-resolving GetInner through the new singleton reference. This replaces physicalStreamingAggWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild gated on isLeafReplaceable. Streaming aggregation is a PRODUCER, not on the ordering-delegation spine, so the emitter has already frozen (or kept live) the ordering-correct inner per arm — extraction recurses through that edge faithfully.

func (*RecordQueryStreamingAggregationPlan) WithQuantifiers

WithQuantifiers rebuilds the aggregation over the given child quantifier. Grouping keys and aggregate operands are evaluation programs over the input edge, so replacing that edge must checked-rebase every exact QOV root before publishing the replacement plan. Reconstructing through the constructor also rebuilds PlanExprBase and the aggregate's output QOV from the rebased values; a shallow copy would retain a stale admitted result contract.

type RecordQueryTableFunctionPlan

type RecordQueryTableFunctionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryTableFunctionPlan delegates row-stream production to an underlying streaming Value (e.g. RangeValue). Leaf plan (no children). Mirrors Java's RecordQueryTableFunctionPlan.

func NewRecordQueryTableFunctionPlan

func NewRecordQueryTableFunctionPlan(streamValue values.Value) (*RecordQueryTableFunctionPlan, error)

func (*RecordQueryTableFunctionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryTableFunctionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryTableFunctionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryTableFunctionPlan) Explain

func (p *RecordQueryTableFunctionPlan) Explain() string

func (*RecordQueryTableFunctionPlan) GetChildren

func (p *RecordQueryTableFunctionPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryTableFunctionPlan) GetCorrelatedToWithoutChildren

func (p *RecordQueryTableFunctionPlan) GetCorrelatedToWithoutChildren() map[values.CorrelationIdentifier]struct{}

GetCorrelatedToWithoutChildren reports the correlations of this plan's stream value, mirroring physicalTableFunctionWrapper.

func (*RecordQueryTableFunctionPlan) GetRecordQueryPlan

func (p *RecordQueryTableFunctionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryTableFunctionPlan) GetResultType

func (p *RecordQueryTableFunctionPlan) GetResultType() values.Type

func (*RecordQueryTableFunctionPlan) GetResultValue

func (p *RecordQueryTableFunctionPlan) GetResultValue() values.Value

GetResultValue returns the table function's STABLE per-instance result value — the single correlation identity a bare table function carries as its own memo expression (RFC-184 W2).

func (*RecordQueryTableFunctionPlan) GetStreamValue

func (p *RecordQueryTableFunctionPlan) GetStreamValue() values.Value

func (*RecordQueryTableFunctionPlan) HashCodeWithoutChildren

func (p *RecordQueryTableFunctionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryTableFunctionPlan) HintCost

HintCost: a table function's row count is opaque at plan time.

func (*RecordQueryTableFunctionPlan) HintOrdering

HintOrdering: a table function's output order is opaque.

func (*RecordQueryTableFunctionPlan) ProvenCardinalities

ProvenCardinalities: a table function's row count is opaque at plan time.

func (*RecordQueryTableFunctionPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryTempTableInsertPlan

type RecordQueryTempTableInsertPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryTempTableInsertPlan inserts the output of an inner plan into a temporary table identified by a correlation alias. The owning flag controls whether this plan owns the temp table lifecycle. Mirrors Java's `com.apple.foundationdb.record.query.plan.plans.RecordQueryTempTableInsertPlan`.

func NewRecordQueryTempTableInsertPlan

func NewRecordQueryTempTableInsertPlan(
	inner RecordQueryPlan,
	alias values.CorrelationIdentifier,
	owning bool,
) (*RecordQueryTempTableInsertPlan, error)

func NewRecordQueryTempTableInsertPlanFromQuantifier

func NewRecordQueryTempTableInsertPlanFromQuantifier(
	innerQ expressions.Quantifier,
	alias values.CorrelationIdentifier,
	owning bool,
) (*RecordQueryTempTableInsertPlan, error)

NewRecordQueryTempTableInsertPlanFromQuantifier builds an insert whose child is a LIVE memo quantifier.

func (*RecordQueryTempTableInsertPlan) EqualsPlanWithoutChildren

func (p *RecordQueryTempTableInsertPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryTempTableInsertPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryTempTableInsertPlan) Explain

func (*RecordQueryTempTableInsertPlan) GetChildren

func (*RecordQueryTempTableInsertPlan) GetInner

func (*RecordQueryTempTableInsertPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryTempTableInsertPlan) GetRecordQueryPlan

func (p *RecordQueryTempTableInsertPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryTempTableInsertPlan) GetResultType

func (p *RecordQueryTempTableInsertPlan) GetResultType() values.Type

func (*RecordQueryTempTableInsertPlan) GetTempTableAlias

func (*RecordQueryTempTableInsertPlan) HashCodeWithoutChildren

func (p *RecordQueryTempTableInsertPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryTempTableInsertPlan) HintCost

HintCost: a temp-table insert emits what it consumed.

func (*RecordQueryTempTableInsertPlan) HintOrdering

HintOrdering: a temp-table insert's output order is not modeled.

func (*RecordQueryTempTableInsertPlan) IsOwning

func (p *RecordQueryTempTableInsertPlan) IsOwning() bool

func (*RecordQueryTempTableInsertPlan) ProvenCardinalities

ProvenCardinalities: a temp-table insert emits what it consumed.

func (*RecordQueryTempTableInsertPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the insert carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the temp-table alias and owning flag, and GetInner re-resolves through the new singleton reference. This replaces physicalTempTableInsertWrapper.WithChildren (RFC-184 W2), whose separate snapshot plan field forced a constructor rebuild.

func (*RecordQueryTempTableInsertPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryTempTableScanPlan

type RecordQueryTempTableScanPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryTempTableScanPlan scans a temporary table identified by a correlation alias. Mirrors Java's `com.apple.foundationdb.record.query.plan.plans.RecordQueryTempTableScanPlan`.

func NewRecordQueryTempTableScanPlan

func NewRecordQueryTempTableScanPlan(alias values.CorrelationIdentifier, flowedType values.Type) (*RecordQueryTempTableScanPlan, error)

func (*RecordQueryTempTableScanPlan) EqualsPlanWithoutChildren

func (p *RecordQueryTempTableScanPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryTempTableScanPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryTempTableScanPlan) Explain

func (p *RecordQueryTempTableScanPlan) Explain() string

func (*RecordQueryTempTableScanPlan) GetChildren

func (p *RecordQueryTempTableScanPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryTempTableScanPlan) GetRecordQueryPlan

func (p *RecordQueryTempTableScanPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryTempTableScanPlan) GetResultType

func (p *RecordQueryTempTableScanPlan) GetResultType() values.Type

func (*RecordQueryTempTableScanPlan) GetResultValue

func (p *RecordQueryTempTableScanPlan) GetResultValue() values.Value

GetResultValue returns the temp-table scan's STABLE per-instance result value — the single correlation identity a bare temp-table scan carries as its own memo expression (RFC-184 W2). Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryTempTableScanPlan) GetTempTableAlias

func (*RecordQueryTempTableScanPlan) HashCodeWithoutChildren

func (p *RecordQueryTempTableScanPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryTempTableScanPlan) HintCost

HintCost: a temp-table scan reads an in-memory buffer of unknown size.

func (*RecordQueryTempTableScanPlan) HintOrdering

HintOrdering: a temp-table scan reads an unordered buffer.

func (*RecordQueryTempTableScanPlan) ProvenCardinalities

ProvenCardinalities: a temp-table's contents are produced at runtime.

func (*RecordQueryTempTableScanPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryTextIndexPlan

type RecordQueryTextIndexPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryTextIndexPlan executes a text index scan. Text indexes work differently from regular indexes — the comparison on a query might be split into multiple sub-scans that are intersected or unioned. Mirrors Java's RecordQueryTextIndexPlan.

This is a STRUCTURE-ONLY port — no execution logic. It implements RecordQueryPlan as a leaf plan (no children).

func NewRecordQueryTextIndexPlan

func NewRecordQueryTextIndexPlan(indexName string, textScan TextScan, flowedType values.Type, reverse bool) (*RecordQueryTextIndexPlan, error)

NewRecordQueryTextIndexPlan constructs a text index plan.

func (*RecordQueryTextIndexPlan) EqualsPlanWithoutChildren

func (p *RecordQueryTextIndexPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares index name, text scan, and reverse.

func (*RecordQueryTextIndexPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryTextIndexPlan) Explain

func (p *RecordQueryTextIndexPlan) Explain() string

Explain renders TextIndexScan(indexName, textComparison).

func (*RecordQueryTextIndexPlan) GetChildren

func (p *RecordQueryTextIndexPlan) GetChildren() []RecordQueryPlan

GetChildren returns nil — text index scans are leaves.

func (*RecordQueryTextIndexPlan) GetIndexName

func (p *RecordQueryTextIndexPlan) GetIndexName() string

GetIndexName returns the index name.

func (*RecordQueryTextIndexPlan) GetRecordQueryPlan

func (p *RecordQueryTextIndexPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryTextIndexPlan) GetResultType

func (p *RecordQueryTextIndexPlan) GetResultType() values.Type

func (*RecordQueryTextIndexPlan) GetTextScan

func (p *RecordQueryTextIndexPlan) GetTextScan() TextScan

GetTextScan returns the text scan descriptor.

func (*RecordQueryTextIndexPlan) HashCodeWithoutChildren

func (p *RecordQueryTextIndexPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes index name + text scan + reverse.

func (*RecordQueryTextIndexPlan) IsReverse

func (p *RecordQueryTextIndexPlan) IsReverse() bool

IsReverse reports the scan direction.

func (*RecordQueryTextIndexPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryTypeFilterPlan

type RecordQueryTypeFilterPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryTypeFilterPlan filters an inner plan's row stream to only those records of one of the specified record types. Mirrors Java's `RecordQueryTypeFilterPlan`.

Uses the record-type discriminator (the implicit int64 ID FDB records carry) to filter without inspecting the row payload.

Result type: same as inner (filter doesn't reshape rows).

func NewRecordQueryTypeFilterPlan

func NewRecordQueryTypeFilterPlan(recordTypes []string, inner RecordQueryPlan) (*RecordQueryTypeFilterPlan, error)

NewRecordQueryTypeFilterPlan constructs a type-filter over the given record-type set + inner plan.

func NewRecordQueryTypeFilterPlanFromQuantifier

func NewRecordQueryTypeFilterPlanFromQuantifier(recordTypes []string, innerQ expressions.Quantifier) (*RecordQueryTypeFilterPlan, error)

NewRecordQueryTypeFilterPlanFromQuantifier builds a type filter whose child is a LIVE memo quantifier (the implementation rule passes ForEachQuantifier(MemoizeExpression(winner))) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / OrderingSourceRef / GetResultValue all resolve through the one live edge (RFC-184 W2). recordTypes is normalised (sorted + deduped).

func (*RecordQueryTypeFilterPlan) EqualsPlanWithoutChildren

func (p *RecordQueryTypeFilterPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares record-type sets.

func (*RecordQueryTypeFilterPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryTypeFilterPlan) Explain

func (p *RecordQueryTypeFilterPlan) Explain() string

Explain renders TypeFilter([T1, T2], inner).

func (*RecordQueryTypeFilterPlan) GetChildren

func (p *RecordQueryTypeFilterPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryTypeFilterPlan) GetInner

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryTypeFilterPlan) GetQuantifiers

func (p *RecordQueryTypeFilterPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryTypeFilterPlan) GetRecordQueryPlan

func (p *RecordQueryTypeFilterPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryTypeFilterPlan) GetRecordTypes

func (p *RecordQueryTypeFilterPlan) GetRecordTypes() []string

GetRecordTypes returns the canonical record-type-name list.

func (*RecordQueryTypeFilterPlan) GetResultType

func (p *RecordQueryTypeFilterPlan) GetResultType() values.Type

GetResultType returns the inner's result type.

func (*RecordQueryTypeFilterPlan) GetResultValue

func (p *RecordQueryTypeFilterPlan) GetResultValue() values.Value

GetResultValue returns the flowed object value of the live child quantifier — a type filter passes its inner's rows through, so the result identity is the inner's, the value physicalTypeFilterWrapper.GetResultValue supplied (RFC-184 W2).

func (*RecordQueryTypeFilterPlan) HashCodeWithoutChildren

func (p *RecordQueryTypeFilterPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes class + record-type set.

func (*RecordQueryTypeFilterPlan) HintCost

HintCost: record-type discrimination over the child stream.

func (*RecordQueryTypeFilterPlan) HintOrdering

func (p *RecordQueryTypeFilterPlan) HintOrdering() properties.Ordering

HintOrdering: a type filter preserves its input's order.

func (*RecordQueryTypeFilterPlan) OrderingSourceRef

func (p *RecordQueryTypeFilterPlan) OrderingSourceRef() *expressions.Reference

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryTypeFilterPlan) ProvenCardinalities

ProvenCardinalities: record-type discrimination removes rows but the model conservatively passes the child's bounds through, matching Java's CardinalitiesVisitor.

func (*RecordQueryTypeFilterPlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the plan carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the record-type set, and GetInner re-resolves through the new singleton reference. This replaces physicalTypeFilterWrapper.WithChildren (RFC-184 W2).

func (*RecordQueryTypeFilterPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryUnionPlan

type RecordQueryUnionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryUnionPlan emits the rows of all input plans concatenated, with neither ordering nor deduplication. It is a Go-specific second physical implementation of a bare UNION ALL.

Despite the class name, this does NOT mirror Java's `RecordQueryUnionPlan`, whose variants require comparison keys and merge ordered streams. Java implements a bare logical UNION ALL as `RecordQueryUnorderedUnionPlan`; Go also has that Java-aligned plan, and retains this overlapping concat plan pending taxonomy cleanup (RFC-190).

Result type matches the first inner's result type. All inners must produce row-compatible streams (the planner's responsibility).

The legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `inners []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2.

func NewRecordQueryUnionPlan

func NewRecordQueryUnionPlan(inners []RecordQueryPlan) (*RecordQueryUnionPlan, error)

NewRecordQueryUnionPlan constructs a UNION ALL over the given inner plans.

func NewRecordQueryUnionPlanFromQuantifiers

func NewRecordQueryUnionPlanFromQuantifiers(childQs []expressions.Quantifier) (*RecordQueryUnionPlan, error)

NewRecordQueryUnionPlanFromQuantifiers builds the union directly over the LIVE leg quantifiers the implement rule already memoized, rather than snapshotting bare plans. The plan is then its own cascades expression carrying the leg edges once — no wrapper storing a second copy (RFC-184 W2).

func (*RecordQueryUnionPlan) ChildrenAsSet

func (p *RecordQueryUnionPlan) ChildrenAsSet() bool

ChildrenAsSet reports that the legs of this set operation are commutative — UNION children are bag-equivalent regardless of order.

func (*RecordQueryUnionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryUnionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren is a constant-discriminated equality — union has no operator-specific node-info beyond its children.

func (*RecordQueryUnionPlan) EqualsWithoutChildren

func (p *RecordQueryUnionPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryUnionPlan) Explain

func (p *RecordQueryUnionPlan) Explain() string

Explain renders Union(inner1, inner2, ...).

func (*RecordQueryUnionPlan) GetChildren

func (p *RecordQueryUnionPlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plans.

func (*RecordQueryUnionPlan) GetInners

func (p *RecordQueryUnionPlan) GetInners() []RecordQueryPlan

GetInners returns the union's inner plans, dereferenced through the quantifiers and in leg order.

func (*RecordQueryUnionPlan) GetQuantifiers

func (p *RecordQueryUnionPlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real leg quantifiers, overriding PlanExprBase's none.

func (*RecordQueryUnionPlan) GetRecordQueryPlan

func (p *RecordQueryUnionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryUnionPlan) GetResultType

func (p *RecordQueryUnionPlan) GetResultType() values.Type

GetResultType returns the first inner's result type, or UnknownType if there are no inners.

func (*RecordQueryUnionPlan) GetResultValue

func (p *RecordQueryUnionPlan) GetResultValue() values.Value

GetResultValue flows the first leg's object value (union legs are column-aligned by construction, so any leg's row shape stands in). Falls back to a fresh quantified object value when there are no legs.

func (*RecordQueryUnionPlan) HashCodeWithoutChildren

func (p *RecordQueryUnionPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren is a constant for the type discriminator.

func (*RecordQueryUnionPlan) HintCost

HintCost: every leg is scanned and concatenated.

func (*RecordQueryUnionPlan) ProvenCardinalities

func (p *RecordQueryUnionPlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: a union concatenates its legs — bounds sum.

func (*RecordQueryUnionPlan) WithChildren

WithChildren rebuilds over fresh leg quantifiers — the optional interface plan extraction uses to preserve the strict-singleton invariant. Delegates to WithQuantifiers; the leg count must match.

func (*RecordQueryUnionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

type RecordQueryUnorderedPrimaryKeyDistinctPlan

type RecordQueryUnorderedPrimaryKeyDistinctPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryUnorderedPrimaryKeyDistinctPlan removes duplicate rows by means of a hash set of primary keys already seen. Unlike RecordQueryDistinctPlan (which deduplicates by full row), this plan deduplicates by primary key only — two rows with the same PK but different projected columns collapse to one.

Mirrors Java's RecordQueryUnorderedPrimaryKeyDistinctPlan. This is a single-child plan: it wraps an inner plan and filters its output stream.

Execution uses the same continuation-carried hash set as unordered value-DISTINCT, keyed by the packed QueryResult primary key. It deliberately has no streaming mode: the child is not required to be primary-key ordered.

func NewRecordQueryUnorderedPrimaryKeyDistinctPlan

func NewRecordQueryUnorderedPrimaryKeyDistinctPlan(inner RecordQueryPlan) (*RecordQueryUnorderedPrimaryKeyDistinctPlan, error)

NewRecordQueryUnorderedPrimaryKeyDistinctPlan constructs a PK-based distinct plan over the given inner plan.

func NewRecordQueryUnorderedPrimaryKeyDistinctPlanFromQuantifier

func NewRecordQueryUnorderedPrimaryKeyDistinctPlanFromQuantifier(
	innerQ expressions.Quantifier,
) (*RecordQueryUnorderedPrimaryKeyDistinctPlan, error)

NewRecordQueryUnorderedPrimaryKeyDistinctPlanFromQuantifier constructs a primary-key distinct plan over the supplied live memo edge.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) EqualsPlanWithoutChildren

func (p *RecordQueryUnorderedPrimaryKeyDistinctPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) Explain

Explain renders UnorderedPrimaryKeyDistinct(inner).

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetChildren

GetChildren returns the inner plan as the only child.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetInner

GetInner returns the wrapped inner plan, dereferenced through the quantifier.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetInnerQuantifier

GetInnerQuantifier returns the plan's single child edge.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetQuantifiers

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetRecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetResultType

GetResultType returns the inner plan's result type — PK-distinct doesn't reshape rows.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) GetResultValue

GetResultValue returns the child row unchanged.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) HashCodeWithoutChildren

func (p *RecordQueryUnorderedPrimaryKeyDistinctPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mirrors Java's BASE_HASH("Record-Query-Unordered-Primary-Key-Distinct-Plan").

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) HintCost

HintCost: primary-key duplicate elimination has the same hash-set work shape as unordered value duplicate elimination.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) HintOrdering

HintOrdering: primary-key duplicate elimination drops rows without reordering the survivors.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) IsReverse

IsReverse delegates to the inner plan.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) OrderingSourceRef

OrderingSourceRef reports the child group this plan's ordering flows from.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) ProvenCardinalities

ProvenCardinalities: primary-key duplicate elimination leaves the maximum unchanged, and any known non-empty input produces at least one unique key.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) WithChildren

WithChildren is the extraction/relink hook. Relinking swaps only the child quantifier and preserves all node-local state.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) WithInner

WithInner returns a copy with a replacement singleton child.

func (*RecordQueryUnorderedPrimaryKeyDistinctPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryUnorderedUnionPlan

type RecordQueryUnorderedUnionPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryUnorderedUnionPlan emits the rows of all input plans concatenated without any ordering guarantee. Mirrors Java's RecordQueryUnorderedUnionPlan.

Go's RecordQueryUnionPlan is another concatenating, no-dedup UNION ALL implementation; it is not merge-sorted. Ordered behavior lives in RecordQueryMergeSortUnionPlan. The two concat plans currently differ in execution/continuation machinery and are tracked for taxonomy cleanup.

The legs are stored ONCE, as Quantifiers over References — Java's shape (`RecordQuerySetPlan`'s `List<Quantifier.Physical> quantifiers`). The raw `inners []RecordQueryPlan` slice they replace was a second storage location for the same edges. RFC-183 P5 step 2.

func NewRecordQueryUnorderedUnionPlan

func NewRecordQueryUnorderedUnionPlan(inners []RecordQueryPlan) (*RecordQueryUnorderedUnionPlan, error)

func NewRecordQueryUnorderedUnionPlanFromQuantifiers

func NewRecordQueryUnorderedUnionPlanFromQuantifiers(childQs []expressions.Quantifier) (*RecordQueryUnorderedUnionPlan, error)

NewRecordQueryUnorderedUnionPlanFromQuantifiers builds the union over the LIVE leg quantifiers the implement rule memoized. Each leg is a SHARED multi-member group whose per-ordering winner is resolved at extraction via ref.Winner() (planFromQuantifier) — the deferred-winner set-op case. The plan carries each leg edge once, with no wrapper snapshot (RFC-184 W2).

func (*RecordQueryUnorderedUnionPlan) ChildrenAsSet

func (p *RecordQueryUnorderedUnionPlan) ChildrenAsSet() bool

ChildrenAsSet reports that the legs of this set operation are commutative, the concatenation imposes no order, so any leg order is equivalent.

func (*RecordQueryUnorderedUnionPlan) EqualsPlanWithoutChildren

func (p *RecordQueryUnorderedUnionPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryUnorderedUnionPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryUnorderedUnionPlan) Explain

func (*RecordQueryUnorderedUnionPlan) GetChildren

func (*RecordQueryUnorderedUnionPlan) GetInners

GetInners returns the legs, dereferenced through the quantifiers. Order is preserved even though the union imposes none on its OUTPUT: it is the concatenation order the executor consumes the legs in.

func (*RecordQueryUnorderedUnionPlan) GetQuantifiers

GetQuantifiers reports the real leg quantifiers, overriding PlanExprBase's none.

func (*RecordQueryUnorderedUnionPlan) GetRecordQueryPlan

func (p *RecordQueryUnorderedUnionPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryUnorderedUnionPlan) GetResultType

func (p *RecordQueryUnorderedUnionPlan) GetResultType() values.Type

func (*RecordQueryUnorderedUnionPlan) GetResultValue

func (p *RecordQueryUnorderedUnionPlan) GetResultValue() values.Value

GetResultValue flows the first leg's object value (union legs are column-aligned, so any leg's shape stands in); falls back to a fresh quantified object value when there are no legs.

func (*RecordQueryUnorderedUnionPlan) HashCodeWithoutChildren

func (p *RecordQueryUnorderedUnionPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryUnorderedUnionPlan) HintCost

HintCost: every leg is scanned and concatenated.

func (*RecordQueryUnorderedUnionPlan) HintOrdering

HintOrdering: an unordered union interleaves its legs arbitrarily.

func (*RecordQueryUnorderedUnionPlan) ProvenCardinalities

ProvenCardinalities: a union concatenates its legs — bounds sum.

func (*RecordQueryUnorderedUnionPlan) WithChildren

WithChildren rebuilds over fresh leg quantifiers — the interface plan extraction uses. Delegates to WithQuantifiers; the leg count must match.

func (*RecordQueryUnorderedUnionPlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given leg quantifiers — Java's copy-on-write withChildrenReferences. The receiver is never mutated, which is what keeps a memoized plan safe to share; the incoming slice is copied so the caller cannot alias the copy's storage either.

type RecordQueryUpdatePlan

type RecordQueryUpdatePlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryUpdatePlan is the physical UPDATE plan: applies a list of per-row transforms to records emitted by an inner plan. Mirrors a simplified subset of Java's `RecordQueryUpdatePlan`.

The transforms list is the same `expressions.UpdateTransform` shape used by the logical UpdateExpression — Java carries them through to the physical plan unchanged.

Result type: the Java-shaped two-field record {OLD: inner, NEW: target}.

func NewRecordQueryUpdatePlan

func NewRecordQueryUpdatePlan(inner RecordQueryPlan, targetRecordType string, transforms []expressions.UpdateTransform) (*RecordQueryUpdatePlan, error)

NewRecordQueryUpdatePlan constructs the UPDATE plan.

func NewRecordQueryUpdatePlanFromQuantifier

func NewRecordQueryUpdatePlanFromQuantifier(innerQ expressions.Quantifier, targetRecordType string, transforms []expressions.UpdateTransform) (*RecordQueryUpdatePlan, error)

NewRecordQueryUpdatePlanFromQuantifier builds an UPDATE whose child is a LIVE memo quantifier (the implementation rule passes ForEachQuantifier(MemoizeExpression(winner))) instead of a snapshot over a single plan. This makes the plan its own cascades expression carrying its child edge directly: the memo holds it without a physical wrapper, and GetInner / GetQuantifiers / GetResultValue all resolve through the one live edge (RFC-184 W2). transforms are copied, unchanged from NewRecordQueryUpdatePlan.

func NewRecordQueryUpdatePlanFromQuantifierWithTargetType

func NewRecordQueryUpdatePlanFromQuantifierWithTargetType(
	innerQ expressions.Quantifier,
	targetRecordType string,
	targetType values.Type,
	transforms []expressions.UpdateTransform,
) (*RecordQueryUpdatePlan, error)

NewRecordQueryUpdatePlanFromQuantifierWithTargetType preserves the target schema carried by the logical UpdateExpression. The legacy convenience constructor derives this from the input because ordinary updates do not change record type; the rule path calls this form so memo admission can prove the exact logical and physical OLD/NEW contracts agree.

func (*RecordQueryUpdatePlan) EqualsPlanWithoutChildren

func (p *RecordQueryUpdatePlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryUpdatePlan) EqualsWithoutChildren

func (p *RecordQueryUpdatePlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryUpdatePlan) Explain

func (p *RecordQueryUpdatePlan) Explain() string

Explain renders Update(target, [N transforms], inner).

func (*RecordQueryUpdatePlan) GetChildren

func (p *RecordQueryUpdatePlan) GetChildren() []RecordQueryPlan

GetChildren returns the inner plan as the only child.

func (*RecordQueryUpdatePlan) GetInner

func (p *RecordQueryUpdatePlan) GetInner() RecordQueryPlan

GetInner returns the source plan, dereferenced through the quantifier.

func (*RecordQueryUpdatePlan) GetQuantifiers

func (p *RecordQueryUpdatePlan) GetQuantifiers() []expressions.Quantifier

GetQuantifiers reports the real child quantifier, overriding PlanExprBase's none.

func (*RecordQueryUpdatePlan) GetRecordQueryPlan

func (p *RecordQueryUpdatePlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryUpdatePlan) GetResultType

func (p *RecordQueryUpdatePlan) GetResultType() values.Type

GetResultType returns the inner's result type.

func (*RecordQueryUpdatePlan) GetResultValue

func (p *RecordQueryUpdatePlan) GetResultValue() values.Value

GetResultValue returns the stable current QOV for {OLD,NEW}.

func (*RecordQueryUpdatePlan) GetTargetRecordType

func (p *RecordQueryUpdatePlan) GetTargetRecordType() string

GetTargetRecordType returns the destination record-type name.

func (*RecordQueryUpdatePlan) GetTargetType

func (p *RecordQueryUpdatePlan) GetTargetType() values.Type

GetTargetType returns a defensive exact target type.

func (*RecordQueryUpdatePlan) GetTransforms

func (p *RecordQueryUpdatePlan) GetTransforms() []expressions.UpdateTransform

GetTransforms returns the per-row transform list (read-only).

func (*RecordQueryUpdatePlan) HashCodeWithoutChildren

func (p *RecordQueryUpdatePlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes class + targetRecordType + per-transform FieldPath and NewValue (semantic hash), pairing with the by-value equality above so equal⟹same-hash holds.

func (*RecordQueryUpdatePlan) HintCost

HintCost: one write per consumed row.

func (*RecordQueryUpdatePlan) ProvenCardinalities

func (p *RecordQueryUpdatePlan) ProvenCardinalities(child []properties.Cardinalities) properties.Cardinalities

ProvenCardinalities: one effect per consumed row.

func (*RecordQueryUpdatePlan) WithChildren

WithChildren is the extraction/relink hook (plan_extraction.go's WithChildren interface). Because the plan carries its child as a single LIVE memo edge, the relink is exactly a quantifier swap: WithQuantifiers preserves the target and transforms, and GetInner re-resolves through the new singleton reference. This replaces physicalUpdateWrapper.WithChildren (RFC-184 W2).

func (*RecordQueryUpdatePlan) WithQuantifiers

WithQuantifiers returns a copy ranging over the given child quantifier — Java's copy-on-write withChild(Reference).

type RecordQueryValuesPlan

type RecordQueryValuesPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryValuesPlan is a leaf physical-plan that produces a single row of constant values — the physical counterpart of LogicalValuesExpression. Mirrors SQL's VALUES (a, b, c) at execution time.

func NewRecordQueryValuesPlan

func NewRecordQueryValuesPlan(columns []values.Value) (*RecordQueryValuesPlan, error)

func (*RecordQueryValuesPlan) EqualsPlanWithoutChildren

func (p *RecordQueryValuesPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

func (*RecordQueryValuesPlan) EqualsWithoutChildren

func (p *RecordQueryValuesPlan) EqualsWithoutChildren(other expressions.RelationalExpression, _ *expressions.AliasMap) bool

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryValuesPlan) Explain

func (p *RecordQueryValuesPlan) Explain() string

func (*RecordQueryValuesPlan) GetChildren

func (p *RecordQueryValuesPlan) GetChildren() []RecordQueryPlan

func (*RecordQueryValuesPlan) GetColumns

func (p *RecordQueryValuesPlan) GetColumns() []values.Value

func (*RecordQueryValuesPlan) GetRecordQueryPlan

func (p *RecordQueryValuesPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryValuesPlan) GetResultType

func (p *RecordQueryValuesPlan) GetResultType() values.Type

func (*RecordQueryValuesPlan) GetResultValue

func (p *RecordQueryValuesPlan) GetResultValue() values.Value

GetResultValue returns the values plan's STABLE per-instance result value — the single correlation identity a bare values plan carries as its own memo expression (RFC-184 W2). Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryValuesPlan) HashCodeWithoutChildren

func (p *RecordQueryValuesPlan) HashCodeWithoutChildren() uint64

func (*RecordQueryValuesPlan) HintCost

HintCost: a literal row source costs nothing to produce.

func (*RecordQueryValuesPlan) ProvenCardinalities

ProvenCardinalities: a literal row source is one deterministic row.

func (*RecordQueryValuesPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

type RecordQueryVectorIndexPlan

type RecordQueryVectorIndexPlan struct {
	PlanExprBase
	// contains filtered or unexported fields
}

RecordQueryVectorIndexPlan is a K-nearest-neighbor scan over a VECTOR (HNSW) index. It is the physical plan the vector index match candidate emits for a query of the shape

SELECT ... FROM t
WHERE <partition keys = ...>
QUALIFY ROW_NUMBER() OVER (PARTITION BY <keys> ORDER BY <distance>(vec, q)) <= k

Unlike RecordQueryIndexPlan (a BY_VALUE prefix scan), this plan executes a BY_DISTANCE scan: the partition-equality prefix selects the independent HNSW graph, and the graph is traversed for the k nearest neighbors of the query vector. Mirrors the scan Java's VectorIndexScanMatchCandidate lowers to (VectorIndexScanComparisons + a DistanceRankValueComparison).

Leaf node — reads index entries (primaryKey + distance) directly from the HNSW subspace; a fetch step loads the base records.

func NewRecordQueryVectorIndexPlan

func NewRecordQueryVectorIndexPlan(
	indexName string,
	prefixComparisons []*predicates.ComparisonRange,
	queryVector values.Value,
	k values.Value,
	rankType predicates.ComparisonType,
	efSearch *int,
	isReturningVectors *bool,
	recordTypes []string,
	flowedType values.Type,
) (*RecordQueryVectorIndexPlan, error)

NewRecordQueryVectorIndexPlan constructs a BY_DISTANCE vector index scan.

func (*RecordQueryVectorIndexPlan) EqualsPlanWithoutChildren

func (p *RecordQueryVectorIndexPlan) EqualsPlanWithoutChildren(other RecordQueryPlan) bool

EqualsWithoutChildren compares index name, prefix comparison shape, and the query-vector / k / ef_search node-info.

func (*RecordQueryVectorIndexPlan) EqualsWithoutChildren

EqualsWithoutChildren is the RelationalExpression-shaped comparison; see planEqualsAsExpression.

func (*RecordQueryVectorIndexPlan) Explain

func (p *RecordQueryVectorIndexPlan) Explain() string

Explain renders a one-line label. The "VectorIndexScan" token is the EXPLAIN-pin anchor used by the conformance tests.

func (*RecordQueryVectorIndexPlan) GetChildren

func (p *RecordQueryVectorIndexPlan) GetChildren() []RecordQueryPlan

GetChildren returns nil — vector scans are leaves.

func (*RecordQueryVectorIndexPlan) GetEfSearch

func (p *RecordQueryVectorIndexPlan) GetEfSearch() *int

GetEfSearch returns the HNSW ef_search knob (nil = default).

func (*RecordQueryVectorIndexPlan) GetIndexName

func (p *RecordQueryVectorIndexPlan) GetIndexName() string

GetIndexName returns the vector index name.

func (*RecordQueryVectorIndexPlan) GetK

GetK returns the top-K Value.

func (*RecordQueryVectorIndexPlan) GetPartitionColumns

func (p *RecordQueryVectorIndexPlan) GetPartitionColumns() []string

GetPartitionColumns returns the partition-key column names in key order.

func (*RecordQueryVectorIndexPlan) GetPartitionKeyComponentTypes

func (p *RecordQueryVectorIndexPlan) GetPartitionKeyComponentTypes() []values.Type

GetPartitionKeyComponentTypes returns physical types aligned with the partition equality-prefix comparisons.

func (*RecordQueryVectorIndexPlan) GetPrefixComparisons

func (p *RecordQueryVectorIndexPlan) GetPrefixComparisons() []*predicates.ComparisonRange

GetPrefixComparisons returns the partition-key equality ranges.

func (*RecordQueryVectorIndexPlan) GetQueryVector

func (p *RecordQueryVectorIndexPlan) GetQueryVector() values.Value

GetQueryVector returns the search-vector Value.

func (*RecordQueryVectorIndexPlan) GetRankType

GetRankType returns the distance-rank comparison operator (LessThan or LessThanOrEq). Used by the executor to derive the scan limit from k.

func (*RecordQueryVectorIndexPlan) GetRecordQueryPlan

func (p *RecordQueryVectorIndexPlan) GetRecordQueryPlan() RecordQueryPlan

GetRecordQueryPlan returns the plan itself.

func (*RecordQueryVectorIndexPlan) GetRecordTypes

func (p *RecordQueryVectorIndexPlan) GetRecordTypes() []string

GetRecordTypes returns the covered record types.

func (*RecordQueryVectorIndexPlan) GetResultType

func (p *RecordQueryVectorIndexPlan) GetResultType() values.Type

GetResultType returns the flowed row type.

func (*RecordQueryVectorIndexPlan) GetResultValue

func (p *RecordQueryVectorIndexPlan) GetResultValue() values.Value

GetResultValue returns the vector scan's STABLE per-instance result value — the single correlation identity a bare vector scan carries as its own memo expression (RFC-184 W2), propagated through the With* struct copies. Falls back to PlanExprBase (a fresh QOV per call) for struct-literal test plans that bypass the constructor (resultValue is nil).

func (*RecordQueryVectorIndexPlan) HashCodeWithoutChildren

func (p *RecordQueryVectorIndexPlan) HashCodeWithoutChildren() uint64

HashCodeWithoutChildren mixes index name + prefix comparison shape.

func (*RecordQueryVectorIndexPlan) HintCost

HintCost: a K-NN probe returns its top-K (or, for an ordered stream, its fixed re-ranked horizon) regardless of table size.

func (*RecordQueryVectorIndexPlan) HintOrdering

HintOrdering: a K-NN probe returns its neighbours in an order the ordering property does not model.

func (*RecordQueryVectorIndexPlan) HintRichOrdering

func (p *RecordQueryVectorIndexPlan) HintRichOrdering() *properties.RichOrdering

HintRichOrdering: an HNSW probe returns its neighbours in distance order, which is not a column ordering the planner models. Empty rather than a synthesized fallback, so no caller mistakes distance order for key order.

func (*RecordQueryVectorIndexPlan) IsOrderedStream

func (p *RecordQueryVectorIndexPlan) IsOrderedStream() bool

IsOrderedStream reports whether the scan runs in VBASE distance-ordered mode (emits its re-ranked horizon in distance order, does NOT self-limit to k). See the orderedStream field doc. RFC-156 Phase B.

func (*RecordQueryVectorIndexPlan) IsReturningVectors

func (p *RecordQueryVectorIndexPlan) IsReturningVectors() bool

IsReturningVectors reports whether the scan returns vector payloads.

func (*RecordQueryVectorIndexPlan) ProvenCardinalities

ProvenCardinalities: a K-NN probe's row count depends on how many neighbours the index actually holds within the probed region, which is not a structural property of the plan.

func (*RecordQueryVectorIndexPlan) WithOrderedStream

WithOrderedStream returns a copy of the plan in distance-ordered (non-self- limiting) mode. The k binding is retained for the SinkLimitIntoVectorScanRule fold and cost estimation, but the executor ignores it in this mode.

func (*RecordQueryVectorIndexPlan) WithPartitionColumns

func (p *RecordQueryVectorIndexPlan) WithPartitionColumns(cols []string) *RecordQueryVectorIndexPlan

WithPartitionColumns returns a copy of the plan carrying the partition-key column names (columnNames[:partitionCount]). Set by the match candidate's ToScanPlan so the planner can certify a partition-column residual as safe.

func (*RecordQueryVectorIndexPlan) WithPartitionKeyComponentTypes

func (p *RecordQueryVectorIndexPlan) WithPartitionKeyComponentTypes(types []values.Type) *RecordQueryVectorIndexPlan

WithPartitionKeyComponentTypes returns a copy carrying authoritative physical partition-key types aligned with GetPrefixComparisons.

func (*RecordQueryVectorIndexPlan) WithQuantifiers

WithQuantifiers returns this plan unchanged — it has no quantifiers to replace while children are raw pointers (RFC-183 P5 step 1).

func (*RecordQueryVectorIndexPlan) WithSelfLimiting

WithSelfLimiting returns a copy of the plan in self-limiting (top-k) mode. SinkLimitIntoVectorScanRule produces this when a Limit(k) sits DIRECTLY above an ordered-stream scan with no intervening residual Filter — restoring the legacy one-shot search(k) path.

type RelativeProbabilityPlanSelector

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

RelativeProbabilityPlanSelector selects a child plan based on relative probabilities. Mirrors Java's inner RelativeProbabilityPlanSelector class.

func NewRelativeProbabilityPlanSelector

func NewRelativeProbabilityPlanSelector(probabilities []int) *RelativeProbabilityPlanSelector

NewRelativeProbabilityPlanSelector constructs the selector. The sum of probabilities must be 100.

func (*RelativeProbabilityPlanSelector) Equals

Equals compares probability lists.

func (*RelativeProbabilityPlanSelector) GetProbabilities

func (s *RelativeProbabilityPlanSelector) GetProbabilities() []int

GetProbabilities returns the probability list.

func (*RelativeProbabilityPlanSelector) SelectPlan

SelectPlan picks a plan index based on the probabilities. (Structural port only; the random-weighted selection logic belongs in the execution layer.)

func (*RelativeProbabilityPlanSelector) String

String renders the probability list.

type ScoreForRank

type ScoreForRank struct {
	BindingName  string
	FunctionName string
	IndexName    string
	Comparisons  []string // typeless comparison strings
}

ScoreForRank is a single conversion of a rank to a score to be bound to some name. Mirrors Java's RecordQueryScoreForRankPlan.ScoreForRank inner class.

Fields:

  • BindingName: the parameter name the converted score is bound to.
  • FunctionName: the aggregate function name (e.g. "rank").
  • IndexName: the index the rank function operates over.
  • Comparisons: human-readable comparison descriptions (structure only — no execution logic in this port).

func (*ScoreForRank) CallString

func (s *ScoreForRank) CallString() string

CallString renders "indexName.functionName(comp1, comp2)".

func (*ScoreForRank) String

func (s *ScoreForRank) String() string

String renders "bindingName = indexName.functionName(comp1, comp2)".

type SortKey

type SortKey struct {
	Field      string
	Desc       bool
	NullsFirst bool
	ValueExpr  values.Value // REQUIRED: the plan-time-baked key Value, evaluated per row
}

SortKey is a sort key + direction for in-memory sorting. ValueExpr is REQUIRED: it carries the key's plan-time-baked Value, which the executor evaluates POSITIONALLY per row. The field-only form (a Field lookup with a nil ValueExpr) is no longer supported — the runtime name fallback was deleted, so the executor rejects a nil ValueExpr as a malformed plan (loud, never a name read; pinned by TestSortCursor_UnbakedKeyIsLoud). Field is DISPLAY-ONLY (Explain + ordering-hint name match). Every planner path that builds a SortKey sets ValueExpr unconditionally (rule_implement_in_memory_sort, rule_implement_streaming_agg).

type TextScan

type TextScan struct {
	// IndexName is the name of the text index being scanned.
	IndexName string
	// GroupingComparisons is a human-readable description of the
	// grouping-key prefix comparisons (may be empty).
	GroupingComparisons string
	// TextComparison is a human-readable description of the text
	// comparison (e.g. "TEXT_CONTAINS_ALL 'hello world'").
	TextComparison string
	// SuffixComparisons is a human-readable description of the suffix
	// comparisons (may be empty).
	SuffixComparisons string
}

TextScan encapsulates the information necessary to scan a text-based index. Mirrors Java's `com.apple.foundationdb.record.query.plan.TextScan`.

This is a STRUCTURE-ONLY port — no execution logic. The fields carry enough information for plan equality, hashing, and explain rendering.

type TranslateValueFunction

type TranslateValueFunction func(
	value values.Value,
	sourceAlias values.CorrelationIdentifier,
	targetAlias values.CorrelationIdentifier,
) (values.Value, bool)

TranslateValueFunction translates a Value from the domain of a fetched full record to the domain of the partial record (index entry) that feeds the fetch. Used by RecordQueryFetchFromPartialRecordPlan to enable push-through rules (pushing filters, maps, set operations below the fetch).

Mirrors Java's `TranslateValueFunction` functional interface.

Jump to

Keyboard shortcuts

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