java.lang.Object
com.darkcollective.relix.processor.exec.RelNodeExecutor

public final class RelNodeExecutor extends Object
Executes a logical relational algebra RelNode tree.

Execution is two-stage: the tree is first planned into a PhysicalNode plan — which fixes each join's algorithm and build side and resolves every node's output schema — and the plan is then run by a PhysicalExecutor, yielding a lazy Stream<Row>. This class is the thin adapter between the two; all operator logic lives in PhysicalExecutor.

Precondition

The ExecutionContext must have been built from a fully-valid SemanticModel: its ExecutionContext.nodeSchemas() must cover node (and any view bodies it references), since the planner reads schemas from there.

Thread safety

Stateless and therefore thread-safe; the streams it returns are not.

  • Constructor Details

    • RelNodeExecutor

      public RelNodeExecutor()
  • Method Details

    • withObservedCardinalities

      public RelNodeExecutor withObservedCardinalities(ObservedCardinalities observed)
      Plans through a cost model that prefers what a previous run measured.

      A wither rather than a constructor argument or a context component: an ExecutionContext is the state of one execution, while a store of measured counts belongs to whatever outlives the executions — a session, typically — and putting it on the context would have made every caller of a ten-component record name a thing it has no opinion about.

      Parameters:
      observed - the recorded counts; must not be null
      Returns:
      this executor, for chaining
    • execute

      public Stream<Row> execute(RelNode node, ExecutionContext ctx)
      Plans and executes node, returning a lazy stream of result rows.

      The stream should be consumed exactly once and closed after use.

      Planning reports its physical decisions to the context's own ExecutionContext.listener() — the same listener the operators emit their EXECUTE events to — so a context that is observing sees the whole run, not only its execution half. A context that is not observing carries QueryEventListener.NONE and nothing is emitted.

      Parameters:
      node - the logical relational algebra node to execute; must not be null
      ctx - the shared execution context; must not be null
      Returns:
      a lazy stream of rows; caller is responsible for closing
      Throws:
      EvaluationException - if a data-level error occurs at runtime
    • execute

      public Stream<Row> execute(RelNode node, ExecutionContext ctx, QueryEventListener planListener)
      As execute(RelNode, ExecutionContext), but reports the planner's decisions to planListener rather than to the context's listener.

      The two differ for a caller that plans the same tree twice and must not report it twice: QueryExecutor.traceExecute has already collected the PLAN events from a separate planning pass, and passes QueryEventListener.NONE here so only the EXECUTE stage reaches the feed a second time.

      Parameters:
      node - the logical relational algebra node to execute; must not be null
      ctx - the shared execution context; must not be null
      planListener - notified on each physical decision; must not be null
      Returns:
      a lazy stream of rows; caller is responsible for closing
      Throws:
      EvaluationException - if a data-level error occurs at runtime
    • plan

      public PhysicalNode plan(RelNode node, ExecutionContext ctx)
      Plans node into a PhysicalNode without executing it — the planning half of execute(com.darkcollective.relix.ast.RelNode, com.darkcollective.relix.processor.internal.ExecutionContext), exposed for --explain.
      Parameters:
      node - the logical relational algebra node to plan; must not be null
      ctx - the shared execution context; must not be null
      Returns:
      the physical plan
    • plan

      public PhysicalNode plan(RelNode node, ExecutionContext ctx, QueryEventListener listener)
      Parameters:
      node - the logical node to plan; must not be null
      ctx - the shared execution context; must not be null
      listener - notified on each physical decision; must not be null
      Returns:
      the physical plan
    • planWithEstimates

      public PlannedQuery planWithEstimates(RelNode node, ExecutionContext ctx, QueryEventListener listener)
      Plans node and returns the plan together with its cardinality estimates — the form --explain and the playground bundle need, since a plan node does not carry its own estimate.
      Parameters:
      node - the logical node to plan; must not be null
      ctx - the shared execution context; must not be null
      listener - notified on each physical decision; must not be null
      Returns:
      the plan and its estimates