java.lang.Object
com.darkcollective.relix.processor.eval.PredicateEvaluator

public final class PredicateEvaluator extends Object
Evaluates a Predicate against a Row, returning a boolean result.

Handles all seven subtypes of the sealed Predicate hierarchy: comparison, logical AND/OR/NOT, null tests, set-membership tests, and pattern (LIKE) matches.

NULL semantics are SQL's three-valued (Kleene) logic, and the evaluator is three-valued internally: a predicate answers PredicateEvaluator.Truth.TRUE, PredicateEvaluator.Truth.FALSE or PredicateEvaluator.Truth.UNKNOWN.

  • Any comparison (=, !=, <, …) with a NULL operand is UNKNOWN — including NULL = NULL.
  • NULL ∈ set is UNKNOWN, and so is x ∈ set when x matches nothing but the set holds a NULL: the answer depends on a value nobody knows.
  • A LIKE against a NULL is UNKNOWN.
  • IS NULL / IS NOT NULL are the only predicates that are never UNKNOWN — asking about the absence itself always has an answer.
  • ¬UNKNOWN is UNKNOWN, which is why a row can survive neither a predicate nor its negation.

evaluate(com.darkcollective.relix.ast.Predicate, com.darkcollective.relix.processor.Row) answers the only question an operator asks — keep this row? — and keeps a row only when the predicate is TRUE. Every consumer (σ, the joins, ∀, COVER) reads that boolean, so the three-valued detail stays inside this class; the one place a truth value becomes data is a ConditionOperand, where UNKNOWN surfaces as NULL rather than as false.

Three-valued is not a preference, it is the only reading under which the engine agrees with itself. A σ the planner folds into a WHERE clause is evaluated by the database, and SQL is three-valued; a two-valued engine returns different rows for the same script depending on whether the predicate was pushed down. NOT LIKE and ∉ were already three-valued at the leaf, so the alternative was not "leave it alone" but "change those too, and guard every renderer". NullSemanticsAgreementTest (relix-connectors-std) holds the two sides together over a live database.

AND and OR still short-circuit, on the value that determines the result on its own: FALSE for AND, TRUE for OR. UNKNOWN determines nothing, so it does not.

Whether two values are equal or ordered is not decided here — that is ValueComparator, which every operator reads, so a predicate means the same thing in a selection as in a join condition. It is where the number rule lives (values of different scale, 1.0 and 1, compare equal) and where a text cell is read as the boolean or timestamp it spells.

  • Constructor Details

    • PredicateEvaluator

      public PredicateEvaluator(OperandEvaluator operandEvaluator)
      Constructs a PredicateEvaluator using the given operand evaluator.
      Parameters:
      operandEvaluator - the evaluator for scalar expressions; must not be null
  • Method Details

    • evaluate

      public boolean evaluate(Predicate predicate, Row row)
      Evaluates predicate against the given row.
      Parameters:
      predicate - the predicate to evaluate; must not be null
      row - the current row; must not be null
      Returns:
      true if the predicate holds, false otherwise
      Throws:
      EvaluationException - if operand evaluation fails