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

Reply via email to