Class OperatorSemantics

java.lang.Object
com.darkcollective.relix.cost.OperatorSemantics

public final class OperatorSemantics extends Object
Centralised operator-property classification consulted by 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 Type
    Method
    Description
    static boolean
    Whether node is 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 boolean
    Whether node preserves the ordering delivered by its first (left) input — i.e., the operator is order-transparent.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • isLeftFilterOperator

      public static boolean isLeftFilterOperator(RelNode node)
      Whether node is 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, so PropertyDeriver categorises them as set-producing operators rather than left-filter operators. CostEstimator groups all five together for row-count estimation (output ≤ left-input rows in every case) and handles the additional two explicitly.

      Monotonicity note (FIX recursion): 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 in RecursiveRefChecker (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:
      true iff node is a left-filter operator
    • preservesInputOrder

      public static boolean preservesInputOrder(RelNode node)
      Whether node preserves 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:
      true iff node passes its input's ordering through unchanged
      See Also: