PropertyDeriver, OrderDeriver, BoundednessChecker,
and CostEstimator.
Each method encodes a single shared operator category — a property that
more than one deriver must classify consistently. Centralising here means
that adding a new RelNode type produces a compile error in each
deriver's exhaustive switch, and the author need only update this class to
declare which shared categories the new type belongs to, then update the
derivers that need non-default behaviour.
BoundednessChecker is already covered by
RelNode.materializationMode() on the node itself and does not
consult this class.
Coverage invariant
Every RelNode type must appear in at least one method below (or
be absent from all, meaning it falls into the conservative default for that
property — order-clearing, breaks distinctness, etc.). The exhaustive
switches in PropertyDeriver and CostEstimator catch any
newly added type that is accidentally omitted here.
-
Method Summary
Modifier and TypeMethodDescriptionstatic booleanisLeftFilterOperator(RelNode node) Whethernodeis a left-filter operator: its output is a row-subset of its left input — the left rows that pass (or fail) an existence test against the right input — without adding columns or forcing deduplication.static booleanpreservesInputOrder(RelNode node) Whethernodepreserves the ordering delivered by its first (left) input — i.e., the operator is order-transparent.
-
Method Details
-
isLeftFilterOperator
Whethernodeis a left-filter operator: its output is a row-subset of its left input — the left rows that pass (or fail) an existence test against the right input — without adding columns or forcing deduplication.True for:
⋉(semi-join) — keeps left rows for which a matching right row exists; both inputs are monotone positions (see below).▷(anti-join) — keeps left rows for which no matching right row exists; only the left input is a monotone position.- pairwise-
∀— keeps left rows for which every right row satisfies the condition.
Note:
−(difference) and÷(division) also output a subset of left-input rows but they enforce deduplication, soPropertyDerivercategorises them as set-producing operators rather than left-filter operators.CostEstimatorgroups all five together for row-count estimation (output ≤ left-input rows in every case) and handles the additional two explicitly.Monotonicity note (
FIXrecursion): a recursive reference is valid in both inputs of⋉— adding rows to either side can only grow the output — but only in the left input of▷, because adding rows to the right side of an anti-join removes output rows. The⋉right-side monotonicity is deliberately explicit inRecursiveRefChecker(relix-semantic, which depends on this module rather than the other way round, hence no link) with a design-decision comment.- Parameters:
node- the operator to classify; must not be null- Returns:
trueiffnodeis a left-filter operator
-
preservesInputOrder
Whethernodepreserves the ordering delivered by its first (left) input — i.e., the operator is order-transparent.True for:
σ(selection) — filters rows but keeps their relative order.λ(limit/offset) — takes an ordered prefix or sub-sequence.ASOF(AS-OF join) — streams probe rows in their left-input order, appending the matched right columns; the left columns (which carry any delivered ordering) are unchanged.- A relation-only
RenameNode— renames the relation label without touching column names or row order; a column-renaming rename invalidates the ordering's column names and therefore does not preserve order.
Order-establishing operators (
τ) are excluded — they impose a new order rather than preserving the input's. All other operators conservatively clear the delivered ordering.- Parameters:
node- the operator to classify; must not be null- Returns:
trueiffnodepasses its input's ordering through unchanged- See Also:
-