Class RelNodeExecutor
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 Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionexecute(RelNode node, ExecutionContext ctx) Plans and executesnode, returning a lazy stream of result rows.execute(RelNode node, ExecutionContext ctx, QueryEventListener planListener) Asexecute(RelNode, ExecutionContext), but reports the planner's decisions toplanListenerrather than to the context's listener.plan(RelNode node, ExecutionContext ctx) Plansnodeinto aPhysicalNodewithout executing it — the planning half ofexecute(com.darkcollective.relix.ast.RelNode, com.darkcollective.relix.processor.internal.ExecutionContext), exposed for--explain.plan(RelNode node, ExecutionContext ctx, QueryEventListener listener) Plansnode, emitting aQueryEventtolistenerfor each physical decision — used byQueryExecutor.trace(com.darkcollective.relix.semantic.SemanticModel, java.util.List<com.darkcollective.relix.ast.RelNode>, com.darkcollective.relix.events.QueryEventListener).planWithEstimates(RelNode node, ExecutionContext ctx, QueryEventListener listener) Plansnodeand returns the plan together with its cardinality estimates — the form--explainand the playground bundle need, since a plan node does not carry its own estimate.Plans through a cost model that prefers what a previous run measured.
-
Constructor Details
-
RelNodeExecutor
public RelNodeExecutor()
-
-
Method Details
-
withObservedCardinalities
Plans through a cost model that prefers what a previous run measured.A wither rather than a constructor argument or a context component: an
ExecutionContextis 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
Plans and executesnode, 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 theirEXECUTEevents to — so a context that is observing sees the whole run, not only its execution half. A context that is not observing carriesQueryEventListener.NONEand nothing is emitted.- Parameters:
node- the logical relational algebra node to execute; must not be nullctx- 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
Asexecute(RelNode, ExecutionContext), but reports the planner's decisions toplanListenerrather 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.traceExecutehas already collected thePLANevents from a separate planning pass, and passesQueryEventListener.NONEhere so only theEXECUTEstage reaches the feed a second time.- Parameters:
node- the logical relational algebra node to execute; must not be nullctx- the shared execution context; must not be nullplanListener- 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
Plansnodeinto aPhysicalNodewithout executing it — the planning half ofexecute(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 nullctx- the shared execution context; must not be null- Returns:
- the physical plan
-
plan
Plansnode, emitting aQueryEventtolistenerfor each physical decision — used byQueryExecutor.trace(com.darkcollective.relix.semantic.SemanticModel, java.util.List<com.darkcollective.relix.ast.RelNode>, com.darkcollective.relix.events.QueryEventListener).- Parameters:
node- the logical node to plan; must not be nullctx- the shared execution context; must not be nulllistener- notified on each physical decision; must not be null- Returns:
- the physical plan
-
planWithEstimates
public PlannedQuery planWithEstimates(RelNode node, ExecutionContext ctx, QueryEventListener listener) Plansnodeand returns the plan together with its cardinality estimates — the form--explainand the playground bundle need, since a plan node does not carry its own estimate.- Parameters:
node- the logical node to plan; must not be nullctx- the shared execution context; must not be nulllistener- notified on each physical decision; must not be null- Returns:
- the plan and its estimates
-