diff --git a/src/validator/CMakeLists.txt b/src/validator/CMakeLists.txt
index 7ea8e730a6a5ddfa739eff52fe81589123278e03..ffe1da36231dd95d7291e65f6eef70dc4afe0128 100644
--- a/src/validator/CMakeLists.txt
+++ b/src/validator/CMakeLists.txt
@@ -5,7 +5,6 @@
 
 nebula_add_library(
     validator_obj OBJECT
-    ExpressionProps.cpp
     Validator.cpp
     AssignmentValidator.cpp
     GoValidator.cpp
diff --git a/src/validator/ExpressionProps.cpp b/src/validator/ExpressionProps.cpp
deleted file mode 100644
index b54a8ddcd6318297e8c58b4409f537c1bc726965..0000000000000000000000000000000000000000
--- a/src/validator/ExpressionProps.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Copyright (c) 2020 vesoft inc. All rights reserved.
- *
- * This source code is licensed under Apache 2.0 License,
- * attached with Common Clause Condition 1.0, found in the LICENSES directory.
- */
-
-#include "validator/ExpressionProps.h"
-
-namespace nebula {
-namespace graph {
-
-void ExpressionProps::insertVarProp(const std::string& outputVar, folly::StringPiece prop) {
-    auto& props = varProps_[outputVar];
-    props.emplace(prop);
-}
-
-void ExpressionProps::insertInputProp(folly::StringPiece prop) {
-    inputProps_.emplace(prop);
-}
-
-void ExpressionProps::insertSrcTagProp(TagID tagId, folly::StringPiece prop) {
-    auto& props = srcTagProps_[tagId];
-    props.emplace(prop);
-}
-
-void ExpressionProps::insertDstTagProp(TagID tagId, folly::StringPiece prop) {
-    auto& props = dstTagProps_[tagId];
-    props.emplace(prop);
-}
-
-void ExpressionProps::insertEdgeProp(EdgeType edgeType, folly::StringPiece prop) {
-    auto& props = edgeProps_[edgeType];
-    props.emplace(prop);
-}
-
-void ExpressionProps::insertTagNameIds(const std::string &name, TagID tagId) {
-    tagNameIds_.emplace(name, tagId);
-}
-
-void ExpressionProps::insertTagProp(TagID tagId, folly::StringPiece prop) {
-    auto& props = tagProps_[tagId];
-    props.emplace(prop);
-}
-
-bool ExpressionProps::isSubsetOfInput(const std::set<folly::StringPiece>& props) {
-    for (auto& prop : props) {
-        if (inputProps_.find(prop) == inputProps_.end()) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool ExpressionProps::isSubsetOfVar(const VarPropMap& props) {
-    for (auto& iter : props) {
-        if (varProps_.find(iter.first) == varProps_.end()) {
-            return false;
-        }
-        for (auto& prop : iter.second) {
-            if (varProps_[iter.first].find(prop) == varProps_[iter.first].end()) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-void ExpressionProps::unionProps(ExpressionProps exprProps) {
-    if (!exprProps.inputProps().empty()) {
-        inputProps_.insert(std::make_move_iterator(exprProps.inputProps().begin()),
-                           std::make_move_iterator(exprProps.inputProps().end()));
-    }
-    if (!exprProps.srcTagProps().empty()) {
-        for (auto& iter : exprProps.srcTagProps()) {
-            srcTagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
-                                            std::make_move_iterator(iter.second.end()));
-        }
-    }
-    if (!exprProps.dstTagProps().empty()) {
-        for (auto& iter : exprProps.dstTagProps()) {
-            dstTagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
-                                            std::make_move_iterator(iter.second.end()));
-        }
-    }
-    if (!exprProps.tagProps().empty()) {
-        for (auto& iter : exprProps.tagProps()) {
-            tagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
-                                         std::make_move_iterator(iter.second.end()));
-        }
-    }
-    if (!exprProps.varProps().empty()) {
-        for (auto& iter : exprProps.varProps()) {
-            varProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
-                                         std::make_move_iterator(iter.second.end()));
-        }
-    }
-    if (!exprProps.edgeProps().empty()) {
-        for (auto& iter : exprProps.edgeProps()) {
-            edgeProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
-                                          std::make_move_iterator(iter.second.end()));
-        }
-    }
-}
-
-}   // namespace graph
-}   // namespace nebula
diff --git a/src/validator/ExpressionProps.h b/src/validator/ExpressionProps.h
deleted file mode 100644
index dd1bb63d5b085942bc80a1e294d6e3cbf6537a59..0000000000000000000000000000000000000000
--- a/src/validator/ExpressionProps.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2020 vesoft inc. All rights reserved.
- *
- * This source code is licensed under Apache 2.0 License,
- * attached with Common Clause Condition 1.0, found in the LICENSES directory.
- */
-
-#ifndef VALIDATOR_EXPRESSIONPROPS_H_
-#define VALIDATOR_EXPRESSIONPROPS_H_
-
-#include <set>
-#include <string>
-#include <unordered_map>
-
-#include <folly/String.h>
-
-#include "common/thrift/ThriftTypes.h"
-
-namespace nebula {
-namespace graph {
-
-class ExpressionProps final {
-public:
-    using TagNameIds = std::unordered_map<std::string, TagID>;
-    using TagIDPropsMap = std::unordered_map<TagID, std::set<folly::StringPiece>>;
-    using EdgePropMap = std::unordered_map<EdgeType, std::set<folly::StringPiece>>;
-    using VarPropMap = std::unordered_map<std::string, std::set<folly::StringPiece>>;
-
-    ExpressionProps() = default;
-    ~ExpressionProps() = default;
-
-    const std::set<folly::StringPiece>& inputProps() const {
-        return inputProps_;
-    }
-    const TagIDPropsMap& srcTagProps() const {
-        return srcTagProps_;
-    }
-    const TagIDPropsMap& dstTagProps() const {
-        return dstTagProps_;
-    }
-    const TagIDPropsMap& tagProps() const {
-        return tagProps_;
-    }
-    const TagNameIds& tagNameIds() const {
-        return tagNameIds_;
-    }
-    const EdgePropMap& edgeProps() const {
-        return edgeProps_;
-    }
-    const VarPropMap& varProps() const {
-        return varProps_;
-    }
-
-    bool hasInputVarProperty() const {
-        return !inputProps_.empty() || !varProps_.empty();
-    }
-
-    bool hasSrcDstTagProperty() const {
-        return !srcTagProps_.empty() || !dstTagProps_.empty();
-    }
-
-    void insertInputProp(folly::StringPiece prop);
-    void insertVarProp(const std::string& outputVar, folly::StringPiece prop);
-    void insertSrcTagProp(TagID tagId, folly::StringPiece prop);
-    void insertDstTagProp(TagID tagId, folly::StringPiece prop);
-    void insertEdgeProp(EdgeType edgeType, folly::StringPiece prop);
-    void insertTagNameIds(const std::string &name, TagID tagId);
-    void insertTagProp(TagID tagId, folly::StringPiece prop);
-    bool isSubsetOfInput(const std::set<folly::StringPiece>& props);
-    bool isSubsetOfVar(const VarPropMap& props);
-    void unionProps(ExpressionProps exprProps);
-
-private:
-    std::set<folly::StringPiece> inputProps_;
-    VarPropMap varProps_;
-    TagIDPropsMap srcTagProps_;
-    TagIDPropsMap dstTagProps_;
-    EdgePropMap edgeProps_;
-    TagIDPropsMap tagProps_;
-    TagNameIds tagNameIds_;
-};
-
-}   // namespace graph
-}   // namespace nebula
-
-#endif   // VALIDATOR_EXPRESSIONPROPS_H_
diff --git a/src/validator/Validator.h b/src/validator/Validator.h
index 2c507bf044c795a1e4080929e029948d5dbfd4b9..c67bf9087de4c10e2863a9c4fa42e1fe50036912 100644
--- a/src/validator/Validator.h
+++ b/src/validator/Validator.h
@@ -12,7 +12,7 @@
 #include "parser/Sentence.h"
 #include "context/ValidateContext.h"
 #include "context/QueryContext.h"
-#include "validator/ExpressionProps.h"
+#include "visitor/DeducePropsVisitor.h"
 
 namespace nebula {
 
diff --git a/src/visitor/DeducePropsVisitor.cpp b/src/visitor/DeducePropsVisitor.cpp
index f007537c44bba27df2d27778d3a90eca63c524b3..0f547b8018ed952694a5601539dff992d91ff817 100644
--- a/src/visitor/DeducePropsVisitor.cpp
+++ b/src/visitor/DeducePropsVisitor.cpp
@@ -9,11 +9,106 @@
 #include <sstream>
 
 #include "context/QueryContext.h"
-#include "validator/ExpressionProps.h"
 
 namespace nebula {
 namespace graph {
 
+// Expression properties
+void ExpressionProps::insertVarProp(const std::string& outputVar, folly::StringPiece prop) {
+    auto& props = varProps_[outputVar];
+    props.emplace(prop);
+}
+
+void ExpressionProps::insertInputProp(folly::StringPiece prop) {
+    inputProps_.emplace(prop);
+}
+
+void ExpressionProps::insertSrcTagProp(TagID tagId, folly::StringPiece prop) {
+    auto& props = srcTagProps_[tagId];
+    props.emplace(prop);
+}
+
+void ExpressionProps::insertDstTagProp(TagID tagId, folly::StringPiece prop) {
+    auto& props = dstTagProps_[tagId];
+    props.emplace(prop);
+}
+
+void ExpressionProps::insertEdgeProp(EdgeType edgeType, folly::StringPiece prop) {
+    auto& props = edgeProps_[edgeType];
+    props.emplace(prop);
+}
+
+void ExpressionProps::insertTagNameIds(const std::string &name, TagID tagId) {
+    tagNameIds_.emplace(name, tagId);
+}
+
+void ExpressionProps::insertTagProp(TagID tagId, folly::StringPiece prop) {
+    auto& props = tagProps_[tagId];
+    props.emplace(prop);
+}
+
+bool ExpressionProps::isSubsetOfInput(const std::set<folly::StringPiece>& props) {
+    for (auto& prop : props) {
+        if (inputProps_.find(prop) == inputProps_.end()) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ExpressionProps::isSubsetOfVar(const VarPropMap& props) {
+    for (auto& iter : props) {
+        if (varProps_.find(iter.first) == varProps_.end()) {
+            return false;
+        }
+        for (auto& prop : iter.second) {
+            if (varProps_[iter.first].find(prop) == varProps_[iter.first].end()) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+void ExpressionProps::unionProps(ExpressionProps exprProps) {
+    if (!exprProps.inputProps().empty()) {
+        inputProps_.insert(std::make_move_iterator(exprProps.inputProps().begin()),
+                           std::make_move_iterator(exprProps.inputProps().end()));
+    }
+    if (!exprProps.srcTagProps().empty()) {
+        for (auto& iter : exprProps.srcTagProps()) {
+            srcTagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
+                                            std::make_move_iterator(iter.second.end()));
+        }
+    }
+    if (!exprProps.dstTagProps().empty()) {
+        for (auto& iter : exprProps.dstTagProps()) {
+            dstTagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
+                                            std::make_move_iterator(iter.second.end()));
+        }
+    }
+    if (!exprProps.tagProps().empty()) {
+        for (auto& iter : exprProps.tagProps()) {
+            tagProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
+                                         std::make_move_iterator(iter.second.end()));
+        }
+    }
+    if (!exprProps.varProps().empty()) {
+        for (auto& iter : exprProps.varProps()) {
+            varProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
+                                         std::make_move_iterator(iter.second.end()));
+        }
+    }
+    if (!exprProps.edgeProps().empty()) {
+        for (auto& iter : exprProps.edgeProps()) {
+            edgeProps_[iter.first].insert(std::make_move_iterator(iter.second.begin()),
+                                          std::make_move_iterator(iter.second.end()));
+        }
+    }
+}
+
+
+// visitor
 DeducePropsVisitor::DeducePropsVisitor(QueryContext *qctx,
                                        GraphSpaceID space,
                                        ExpressionProps *exprProps)
diff --git a/src/visitor/DeducePropsVisitor.h b/src/visitor/DeducePropsVisitor.h
index 646e98fb616a551655e8709beec00ff1b9ef75d0..7b29bd6fd398abb549c67bb892c121fd01f33747 100644
--- a/src/visitor/DeducePropsVisitor.h
+++ b/src/visitor/DeducePropsVisitor.h
@@ -18,7 +18,67 @@ class Expression;
 namespace graph {
 
 class QueryContext;
-class ExpressionProps;
+
+class ExpressionProps final {
+public:
+    using TagNameIds = std::unordered_map<std::string, TagID>;
+    using TagIDPropsMap = std::unordered_map<TagID, std::set<folly::StringPiece>>;
+    using EdgePropMap = std::unordered_map<EdgeType, std::set<folly::StringPiece>>;
+    using VarPropMap = std::unordered_map<std::string, std::set<folly::StringPiece>>;
+
+    ExpressionProps() = default;
+    ~ExpressionProps() = default;
+
+    const std::set<folly::StringPiece>& inputProps() const {
+        return inputProps_;
+    }
+    const TagIDPropsMap& srcTagProps() const {
+        return srcTagProps_;
+    }
+    const TagIDPropsMap& dstTagProps() const {
+        return dstTagProps_;
+    }
+    const TagIDPropsMap& tagProps() const {
+        return tagProps_;
+    }
+    const TagNameIds& tagNameIds() const {
+        return tagNameIds_;
+    }
+    const EdgePropMap& edgeProps() const {
+        return edgeProps_;
+    }
+    const VarPropMap& varProps() const {
+        return varProps_;
+    }
+
+    bool hasInputVarProperty() const {
+        return !inputProps_.empty() || !varProps_.empty();
+    }
+
+    bool hasSrcDstTagProperty() const {
+        return !srcTagProps_.empty() || !dstTagProps_.empty();
+    }
+
+    void insertInputProp(folly::StringPiece prop);
+    void insertVarProp(const std::string& outputVar, folly::StringPiece prop);
+    void insertSrcTagProp(TagID tagId, folly::StringPiece prop);
+    void insertDstTagProp(TagID tagId, folly::StringPiece prop);
+    void insertEdgeProp(EdgeType edgeType, folly::StringPiece prop);
+    void insertTagNameIds(const std::string &name, TagID tagId);
+    void insertTagProp(TagID tagId, folly::StringPiece prop);
+    bool isSubsetOfInput(const std::set<folly::StringPiece>& props);
+    bool isSubsetOfVar(const VarPropMap& props);
+    void unionProps(ExpressionProps exprProps);
+
+private:
+    std::set<folly::StringPiece> inputProps_;
+    VarPropMap varProps_;
+    TagIDPropsMap srcTagProps_;
+    TagIDPropsMap dstTagProps_;
+    EdgePropMap edgeProps_;
+    TagIDPropsMap tagProps_;
+    TagNameIds tagNameIds_;
+};
 
 class DeducePropsVisitor : public ExprVisitorImpl {
 public: