gortiz commented on code in PR #14296: URL: https://github.com/apache/pinot/pull/14296#discussion_r1820949703
########## pinot-query-planner/src/main/java/org/apache/pinot/query/planner/plannode/PlanNodeVisitor.java: ########## @@ -63,4 +63,150 @@ public interface PlanNodeVisitor<T, C> { T visitExchange(ExchangeNode exchangeNode, C context); T visitExplained(ExplainedNode node, C context); + + /** + * A depth-first visitor that visits all children of a node before visiting the node itself. + * + * The default implementation for each plan node type does nothing but visiting its inputs + * (see {@link #visitChildren(PlanNode, Object)}) and then returning the result of calling + * {@link #defaultCase(PlanNode, Object)}. + * + * Subclasses can override each method to provide custom behavior for each plan node type. + * For example: + * + * <pre> + * public ResultClass visitMailboxSend(MailboxSendNode node, ContextClass context) { + * somethingToDoBeforeChildren(node); + * visitChildren(node, context); + * return somethingToDoAfterChildren(node); + * } + * </pre> + * + * It is not mandatory to override all methods nor to call {@link #visitChildren(PlanNode, Object)} when + * overriding a visit method. + * + * Notice that {@link MailboxReceiveNode} nodes do not have inputs. Instead, they may store the sender node in a + * different field. Whether to visit the sender node when visiting a {@link MailboxReceiveNode} is controlled by + * {@link #traverseStageBoundary()}. + * + * @param <T> + * @param <C> + */ + abstract class DepthFirstVisitor<T, C> implements PlanNodeVisitor<T, C> { + + /** + * Visits all children of a node. + * + * Notice that {@link MailboxReceiveNode} nodes do not have inputs and therefore this method is a no-op for them. + * The default {@link #visitMailboxReceive(MailboxReceiveNode, Object)} implementation will visit the sender node + * if {@link #traverseStageBoundary()} returns true, but if it is overridden, it is up to the implementor to decide + * whether to visit the sender node or not. + */ + protected void visitChildren(PlanNode node, C context) { + for (PlanNode input : node.getInputs()) { + input.visit(this, context); + } + } + + /** + * Whether to visit the sender node (going to another stage) when visiting a {@link MailboxReceiveNode}. + * + * Defaults to true. + */ + protected boolean traverseStageBoundary() { + return true; + } + + /** + * The method that is called by default to handle a node that does not have a specific visit method. + * + * This method can be overridden to provide a default behavior for all nodes. + * + * The returned value of this method is what each default visit method will return. + */ + protected T defaultCase(PlanNode node, C context) { + return null; + } + + @Override + public T visitAggregate(AggregateNode node, C context) { + visitChildren(node, context); + return defaultCase(node, context); + } + + @Override + public T visitFilter(FilterNode node, C context) { + visitChildren(node, context); + return defaultCase(node, context); + } + + @Override + public T visitJoin(JoinNode node, C context) { + visitChildren(node, context); + return defaultCase(node, context); + } + + @Override + public T visitMailboxReceive(MailboxReceiveNode node, C context) { + visitChildren(node, context); Review Comment: > I guess this isn't required given https://github.com/apache/pinot/pull/14294? It is just for completeness in case in future they may have children, although that seems improbable so we can remove this line, yes. > Although I'm curious why we didn't just model the sender node as an input to the receiver node? I think that was a decision taken long before I was focused on MSQ. But I bet it was related to the fact that receive nodes are the boundries of the stage and as indicated by its javadoc, the PlanNodes were treat mostly as a way to represent stages before sending them through the network, so it wasn't useful to consider that the send node is a children of the receive node. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org