java.lang.Object
com.darkcollective.relix.semantic.internal.RelationDeterminism

public final class RelationDeterminism extends Object
Answers one question about a relational expression: would evaluating it twice necessarily give the same relation?

Rewrites that change how many times an expression is evaluated need this. The motivating one is lateral decorrelation (LATERAL-001) and its runtime twin, the lateral argument-tuple memo: both replace "evaluate the function body once per outer row" with "evaluate it once and reuse the rows", which is answer-preserving exactly when the body is reproducible.

What makes an expression irreproducible

  • A function call the supplied FunctionCatalog does not tag FunctionProperty.DETERMINISTIC — Rand(), NOW(), CURRENT_DATE, CURRENT_TIME, and every user-defined scalar function, which is in no library at all. Treating an unrecognised name as irreproducible is the conservative direction and matches DIST-002.
  • An unseeded sampling operator, via RelNodeOperands.usesSystemState(RelNode).
  • Anything reached through a named view or a nested table-valued function: a body that reads nothing volatile itself can still call one that does, so both are resolved through the symbol table and walked.

What it deliberately does not treat as irreproducible

A base relation. Re-reading a source table could in principle return different rows — but the engine already assumes a source is stable for the duration of a query: × materialises its right input once and replays it for every left row, and every hash join, ÷ and set operation does the same. A rewrite that reuses one evaluation of a scan is therefore taking a liberty the executor takes already, not a new one.

Completeness

The walk is built on RelNodeOperands, whose switch over the sealed RelNode hierarchy has no default arm. A new node kind — or a new expression on an existing one — does not compile until it is registered there, so this predicate cannot silently start returning true for something it has never seen. That property is the whole reason the walker exists.

  • Method Details

    • isDeterministic

      public static boolean isDeterministic(RelNode node, SymbolTable symbols, FunctionCatalog functions)
      Returns whether node evaluates to the same relation every time it is run.

      A false answer is always safe to act on; a true answer is only given when nothing volatile was found anywhere in the expression, including through the views and table-valued functions it references.

      Parameters:
      node - the expression to classify; must not be null
      symbols - the table used to resolve view and TVF references; must not be null
      functions - the functions the expression was analysed against, consulted for the FunctionProperty.DETERMINISTIC tag; must not be null. An empty catalogue answers false for every call, which is the safe direction
      Returns:
      true when the expression is reproducible