diff --git a/src/executor/logic/LoopExecutor.h b/src/executor/logic/LoopExecutor.h
index 231feea87762d0d6a8596384a3f9c44aba756504..7e27834adf2b779fd224bae7569efeb218635c41 100644
--- a/src/executor/logic/LoopExecutor.h
+++ b/src/executor/logic/LoopExecutor.h
@@ -4,8 +4,8 @@
  * attached with Common Clause Condition 1.0, found in the LICENSES directory.
  */
 
-#ifndef EXECUTOR_QUERY_LOOPEXECUTOR_H_
-#define EXECUTOR_QUERY_LOOPEXECUTOR_H_
+#ifndef EXECUTOR_LOGIC_LOOPEXECUTOR_H_
+#define EXECUTOR_LOGIC_LOOPEXECUTOR_H_
 
 #include "executor/Executor.h"
 
@@ -30,4 +30,4 @@ private:
 }   // namespace graph
 }   // namespace nebula
 
-#endif   // EXECUTOR_QUERY_LOOPEXECUTOR_H_
+#endif   // EXECUTOR_LOGIC_LOOPEXECUTOR_H_
diff --git a/src/executor/logic/PassThroughExecutor.h b/src/executor/logic/PassThroughExecutor.h
index 640dc8c37e15d3e3bb0c4af180e68ee44d7d298b..6007b73422d770de0a2ac6aaaf0804a54e08eb7f 100644
--- a/src/executor/logic/PassThroughExecutor.h
+++ b/src/executor/logic/PassThroughExecutor.h
@@ -4,13 +4,8 @@
  * attached with Common Clause Condition 1.0, found in the LICENSES directory.
  */
 
-#ifndef EXEC_QUERY_PASSTHROUGHEXECUTOR_H_
-#define EXEC_QUERY_PASSTHROUGHEXECUTOR_H_
-
-#include <unordered_map>
-
-#include <folly/SpinLock.h>
-#include <folly/futures/SharedPromise.h>
+#ifndef EXECUTOR_LOGIC_PASSTHROUGHEXECUTOR_H_
+#define EXECUTOR_LOGIC_PASSTHROUGHEXECUTOR_H_
 
 #include "executor/Executor.h"
 
@@ -19,7 +14,7 @@ namespace graph {
 
 class PassThroughExecutor final : public Executor {
 public:
-    PassThroughExecutor(const PlanNode *node, QueryContext* qctx)
+    PassThroughExecutor(const PlanNode* node, QueryContext* qctx)
         : Executor("PassThroughExecutor", node, qctx) {}
 
     folly::Future<Status> execute() override;
@@ -28,4 +23,4 @@ public:
 }   // namespace graph
 }   // namespace nebula
 
-#endif   // EXEC_QUERY_PASSTHROUGHEXECUTOR_H_
+#endif   // EXECUTOR_LOGIC_PASSTHROUGHEXECUTOR_H_
diff --git a/src/executor/logic/SelectExecutor.h b/src/executor/logic/SelectExecutor.h
index d9f628026a576e1a4d50244ae0d1d7291c5d533f..8ff4e1cb21be5f8b61668878356259a8e3615e7c 100644
--- a/src/executor/logic/SelectExecutor.h
+++ b/src/executor/logic/SelectExecutor.h
@@ -4,8 +4,8 @@
  * attached with Common Clause Condition 1.0, found in the LICENSES directory.
  */
 
-#ifndef EXECUTOR_QUERY_SELECTEXECUTOR_H_
-#define EXECUTOR_QUERY_SELECTEXECUTOR_H_
+#ifndef EXECUTOR_LOGIC_SELECTEXECUTOR_H_
+#define EXECUTOR_LOGIC_SELECTEXECUTOR_H_
 
 #include "executor/Executor.h"
 
@@ -34,4 +34,4 @@ private:
 }   // namespace graph
 }   // namespace nebula
 
-#endif   // EXECUTOR_QUERY_SELECTEXECUTOR_H_
+#endif   // EXECUTOR_LOGIC_SELECTEXECUTOR_H_
diff --git a/src/executor/logic/StartExecutor.h b/src/executor/logic/StartExecutor.h
index da429ce22aa1deae92d700db82e42546aee9f4c1..b643cd718344ea0e05a5b086f2700c6b1ffe7bc5 100644
--- a/src/executor/logic/StartExecutor.h
+++ b/src/executor/logic/StartExecutor.h
@@ -4,8 +4,8 @@
  * attached with Common Clause Condition 1.0, found in the LICENSES directory.
  */
 
-#ifndef EXECUTOR_QUERY_STARTEXECUTOR_H_
-#define EXECUTOR_QUERY_STARTEXECUTOR_H_
+#ifndef EXECUTOR_LOGIC_STARTEXECUTOR_H_
+#define EXECUTOR_LOGIC_STARTEXECUTOR_H_
 
 #include "executor/Executor.h"
 
@@ -23,4 +23,4 @@ public:
 }   // namespace graph
 }   // namespace nebula
 
-#endif   // EXECUTOR_QUERY_STARTEXECUTOR_H_
+#endif   // EXECUTOR_LOGIC_STARTEXECUTOR_H_
diff --git a/src/planner/PlanNode.cpp b/src/planner/PlanNode.cpp
index 347af8311a9fbfbe830088f9653565fd4d4229d9..b25ad81fbaffd94aa35efb8095196699e6037521 100644
--- a/src/planner/PlanNode.cpp
+++ b/src/planner/PlanNode.cpp
@@ -191,7 +191,7 @@ std::ostream& operator<<(std::ostream& os, PlanNode::Kind kind) {
 std::unique_ptr<cpp2::PlanNodeDescription> SingleDependencyNode::explain() const {
     auto desc = PlanNode::explain();
     DCHECK(!desc->__isset.dependencies);
-    desc->set_dependencies({dependency_->id()});
+    desc->set_dependencies({dep()->id()});
     return desc;
 }
 
@@ -204,7 +204,7 @@ std::unique_ptr<cpp2::PlanNodeDescription> SingleInputNode::explain() const {
 std::unique_ptr<cpp2::PlanNodeDescription> BiInputNode::explain() const {
     auto desc = PlanNode::explain();
     DCHECK(!desc->__isset.dependencies);
-    desc->set_dependencies({left_->id(), right_->id()});
+    desc->set_dependencies({left()->id(), right()->id()});
     addDescription("leftVar", leftVar_, desc.get());
     addDescription("rightVar", rightVar_, desc.get());
     return desc;
diff --git a/src/planner/PlanNode.h b/src/planner/PlanNode.h
index b678ce44ed67ec8aab6adf4292ba2da8cfc0737a..7af43b8deac96bdfc5ef86c2ddc93df5b2a59042 100644
--- a/src/planner/PlanNode.h
+++ b/src/planner/PlanNode.h
@@ -138,6 +138,20 @@ public:
         colNames_ = cols;
     }
 
+    const PlanNode* dep(size_t index = 0) const {
+        DCHECK_LT(index, dependencies_.size());
+        return dependencies_.at(index);
+    }
+
+    void setDep(size_t index, const PlanNode* dep) {
+        DCHECK_LT(index, dependencies_.size());
+        dependencies_[index] = DCHECK_NOTNULL(dep);
+    }
+
+    const std::vector<const PlanNode*>& dependencies() const {
+        return dependencies_;
+    }
+
     static const char* toString(Kind kind);
 
 protected:
@@ -147,6 +161,7 @@ protected:
     int64_t                                  id_{-1};
     std::string                              outputVar_;
     std::vector<std::string>                 colNames_;
+    std::vector<const PlanNode*>             dependencies_;
 };
 
 std::ostream& operator<<(std::ostream& os, PlanNode::Kind kind);
@@ -157,21 +172,17 @@ std::ostream& operator<<(std::ostream& os, PlanNode::Kind kind);
 // It's useful for admin plan node
 class SingleDependencyNode : public PlanNode {
 public:
-    const PlanNode* dep() const {
-        return dependency_;
-    }
-
-    void dependsOn(PlanNode *dep) {
-        dependency_ = DCHECK_NOTNULL(dep);
+    void dependsOn(const PlanNode* dep) {
+        setDep(0, dep);
     }
 
 protected:
     SingleDependencyNode(int64_t id, Kind kind, const PlanNode* dep)
-        : PlanNode(id, kind), dependency_(dep) {}
+        : PlanNode(id, kind) {
+        dependencies_.emplace_back(dep);
+    }
 
     std::unique_ptr<cpp2::PlanNodeDescription> explain() const override;
-
-    const PlanNode *dependency_;
 };
 
 class SingleInputNode : public SingleDependencyNode {
@@ -198,11 +209,11 @@ protected:
 class BiInputNode : public PlanNode {
 public:
     void setLeft(const PlanNode* left) {
-        left_ = left;
+        setDep(0, left);
     }
 
     void setRight(const PlanNode* right) {
-        right_ = right;
+        setDep(1, right);
     }
 
     void setLeftVar(std::string leftVar) {
@@ -214,11 +225,11 @@ public:
     }
 
     const PlanNode* left() const {
-        return left_;
+        return dep(0);
     }
 
     const PlanNode* right() const {
-        return right_;
+        return dep(1);
     }
 
     const std::string& leftInputVar() const {
@@ -233,11 +244,11 @@ public:
 
 protected:
     BiInputNode(int64_t id, Kind kind, PlanNode* left, PlanNode* right)
-        : PlanNode(id, kind), left_(left), right_(right) {
+        : PlanNode(id, kind) {
+        dependencies_.emplace_back(DCHECK_NOTNULL(left));
+        dependencies_.emplace_back(DCHECK_NOTNULL(right));
     }
 
-    const PlanNode* left_{nullptr};
-    const PlanNode* right_{nullptr};
     // Datasource for this node.
     std::string leftVar_;
     std::string rightVar_;
diff --git a/src/validator/Validator.cpp b/src/validator/Validator.cpp
index 1b98c50e005c3fe4bdd08391311091e52cf4885d..d33c949ed49a4a5b5ece47fa2894bca1e64b8060 100644
--- a/src/validator/Validator.cpp
+++ b/src/validator/Validator.cpp
@@ -210,79 +210,18 @@ Status Validator::validate(Sentence* sentence, QueryContext* qctx) {
 }
 
 Status Validator::appendPlan(PlanNode* node, PlanNode* appended) {
-    switch (DCHECK_NOTNULL(node)->kind()) {
-        case PlanNode::Kind::kShowHosts:
-        case PlanNode::Kind::kFilter:
-        case PlanNode::Kind::kProject:
-        case PlanNode::Kind::kSort:
-        case PlanNode::Kind::kLimit:
-        case PlanNode::Kind::kAggregate:
-        case PlanNode::Kind::kSelect:
-        case PlanNode::Kind::kLoop:
-        case PlanNode::Kind::kCreateUser:
-        case PlanNode::Kind::kDropUser:
-        case PlanNode::Kind::kUpdateUser:
-        case PlanNode::Kind::kGrantRole:
-        case PlanNode::Kind::kRevokeRole:
-        case PlanNode::Kind::kChangePassword:
-        case PlanNode::Kind::kListUserRoles:
-        case PlanNode::Kind::kListUsers:
-        case PlanNode::Kind::kListRoles:
-        case PlanNode::Kind::kPassThrough:
-        case PlanNode::Kind::kSwitchSpace:
-        case PlanNode::Kind::kGetEdges:
-        case PlanNode::Kind::kGetVertices:
-        case PlanNode::Kind::kCreateSpace:
-        case PlanNode::Kind::kCreateTag:
-        case PlanNode::Kind::kCreateEdge:
-        case PlanNode::Kind::kDescSpace:
-        case PlanNode::Kind::kDescTag:
-        case PlanNode::Kind::kDescEdge:
-        case PlanNode::Kind::kInsertVertices:
-        case PlanNode::Kind::kInsertEdges:
-        case PlanNode::Kind::kGetNeighbors:
-        case PlanNode::Kind::kAlterTag:
-        case PlanNode::Kind::kAlterEdge:
-        case PlanNode::Kind::kShowCreateSpace:
-        case PlanNode::Kind::kShowCreateTag:
-        case PlanNode::Kind::kShowCreateEdge:
-        case PlanNode::Kind::kDropSpace:
-        case PlanNode::Kind::kDropTag:
-        case PlanNode::Kind::kDropEdge:
-        case PlanNode::Kind::kShowSpaces:
-        case PlanNode::Kind::kShowTags:
-        case PlanNode::Kind::kShowEdges:
-        case PlanNode::Kind::kCreateSnapshot:
-        case PlanNode::Kind::kDropSnapshot:
-        case PlanNode::Kind::kSubmitJob:
-        case PlanNode::Kind::kShowSnapshots:
-        case PlanNode::Kind::kBalanceLeaders:
-        case PlanNode::Kind::kBalance:
-        case PlanNode::Kind::kStopBalance:
-        case PlanNode::Kind::kShowBalance:
-        case PlanNode::Kind::kDeleteVertices:
-        case PlanNode::Kind::kDeleteEdges:
-        case PlanNode::Kind::kUpdateVertex:
-        case PlanNode::Kind::kUpdateEdge:
-        case PlanNode::Kind::kShowParts:
-        case PlanNode::Kind::kShowCharset:
-        case PlanNode::Kind::kShowCollation:
-        case PlanNode::Kind::kShowConfigs:
-        case PlanNode::Kind::kSetConfig:
-        case PlanNode::Kind::kGetConfig: {
-            static_cast<SingleDependencyNode*>(node)->dependsOn(appended);
-            break;
-        }
-        default: {
-            return Status::SemanticError("%s not support to append an input.",
-                                         PlanNode::toString(node->kind()));
-        }
+    DCHECK(node != nullptr);
+    DCHECK(appended != nullptr);
+    if (node->dependencies().size() != 1) {
+        return Status::SemanticError("%s not support to append an input.",
+                                     PlanNode::toString(node->kind()));
     }
+    static_cast<SingleDependencyNode*>(node)->dependsOn(appended);
     return Status::OK();
 }
 
 Status Validator::appendPlan(PlanNode* root) {
-    return appendPlan(tail_, DCHECK_NOTNULL(root));
+    return appendPlan(tail_, root);
 }
 
 Status Validator::validate() {
@@ -1021,4 +960,3 @@ void ExpressionProps::unionProps(ExpressionProps exprProps) {
 }
 }   // namespace graph
 }   // namespace nebula
-
diff --git a/src/validator/test/ValidatorTestBase.cpp b/src/validator/test/ValidatorTestBase.cpp
index 0c2bf43e418f4cebe2ce8932f03374d835e729d5..525c0a887422dcd347702749be4b98c8a9c4094a 100644
--- a/src/validator/test/ValidatorTestBase.cpp
+++ b/src/validator/test/ValidatorTestBase.cpp
@@ -36,89 +36,32 @@ void ValidatorTestBase::bfsTraverse(const PlanNode *root, std::vector<PlanNode::
         visited.emplace(node->id());
         result.emplace_back(node->kind());
 
-        switch (node->kind()) {
-            case PlanNode::Kind::kUnknown:
-                ASSERT_TRUE(false) << "Unknown Plan Node.";
-            case PlanNode::Kind::kStart: {
-                break;
-            }
-            case PlanNode::Kind::kCreateUser:
-            case PlanNode::Kind::kDropUser:
-            case PlanNode::Kind::kUpdateUser:
-            case PlanNode::Kind::kGrantRole:
-            case PlanNode::Kind::kRevokeRole:
-            case PlanNode::Kind::kChangePassword:
-            case PlanNode::Kind::kListUserRoles:
-            case PlanNode::Kind::kListUsers:
-            case PlanNode::Kind::kListRoles:
-            case PlanNode::Kind::kShowHosts:
-            case PlanNode::Kind::kGetNeighbors:
-            case PlanNode::Kind::kGetVertices:
-            case PlanNode::Kind::kGetEdges:
-            case PlanNode::Kind::kIndexScan:
-            case PlanNode::Kind::kFilter:
-            case PlanNode::Kind::kProject:
-            case PlanNode::Kind::kSort:
-            case PlanNode::Kind::kLimit:
-            case PlanNode::Kind::kAggregate:
-            case PlanNode::Kind::kSwitchSpace:
-            case PlanNode::Kind::kPassThrough:
-            case PlanNode::Kind::kDedup:
-            case PlanNode::Kind::kDataCollect:
-            case PlanNode::Kind::kCreateSpace:
-            case PlanNode::Kind::kCreateTag:
-            case PlanNode::Kind::kCreateEdge:
-            case PlanNode::Kind::kDescSpace:
-            case PlanNode::Kind::kDescTag:
-            case PlanNode::Kind::kDescEdge:
-            case PlanNode::Kind::kInsertVertices:
-            case PlanNode::Kind::kInsertEdges:
-            case PlanNode::Kind::kShowCreateSpace:
-            case PlanNode::Kind::kShowCreateTag:
-            case PlanNode::Kind::kShowCreateEdge:
-            case PlanNode::Kind::kDropSpace:
-            case PlanNode::Kind::kDropTag:
-            case PlanNode::Kind::kDropEdge:
-            case PlanNode::Kind::kShowSpaces:
-            case PlanNode::Kind::kShowTags:
-            case PlanNode::Kind::kShowEdges:
-            case PlanNode::Kind::kCreateSnapshot:
-            case PlanNode::Kind::kDropSnapshot:
-            case PlanNode::Kind::kShowSnapshots:
-            case PlanNode::Kind::kDataJoin:
-            case PlanNode::Kind::kDeleteVertices:
-            case PlanNode::Kind::kDeleteEdges:
-            case PlanNode::Kind::kUpdateVertex:
-            case PlanNode::Kind::kUpdateEdge: {
-                auto *current = static_cast<const SingleDependencyNode *>(node);
-                queue.emplace(current->dep());
+        if (node->kind() == PlanNode::Kind::kUnknown) {
+            ASSERT_TRUE(false) << "Unknown Plan Node.";
+        }
+
+        switch (node->dependencies().size()) {
+            case 1: {
+                auto *sNode = static_cast<const SingleDependencyNode *>(node);
+                queue.emplace(sNode->dep());
+                if (node->kind() == PlanNode::Kind::kSelect) {
+                    auto *current = static_cast<const Select *>(node);
+                    queue.emplace(current->then());
+                    if (current->otherwise() != nullptr) {
+                        queue.emplace(current->otherwise());
+                    }
+                } else if (node->kind() == PlanNode::Kind::kLoop) {
+                    auto *current = static_cast<const Loop *>(node);
+                    queue.emplace(current->body());
+                }
                 break;
             }
-            case PlanNode::Kind::kUnion:
-            case PlanNode::Kind::kIntersect:
-            case PlanNode::Kind::kMinus: {
+            case 2: {
                 auto *current = static_cast<const BiInputNode *>(node);
                 queue.emplace(current->left());
                 queue.emplace(current->right());
                 break;
             }
-            case PlanNode::Kind::kSelect: {
-                auto *current = static_cast<const Select *>(node);
-                queue.emplace(current->dep());
-                queue.emplace(current->then());
-                if (current->otherwise() != nullptr) {
-                    queue.emplace(current->otherwise());
-                }
-                break;
-            }
-            case PlanNode::Kind::kLoop: {
-                auto *current = static_cast<const Loop *>(node);
-                queue.emplace(current->dep());
-                queue.emplace(current->body());
-                break;
-            }
-            default:
-                LOG(FATAL) << "Unknown PlanNode: " << static_cast<int64_t>(node->kind());
         }
     }
 }