diff --git a/src/graph/visitor/PrunePropertiesVisitor.cpp b/src/graph/visitor/PrunePropertiesVisitor.cpp index 4ea46db4856..bd50bd7b9ac 100644 --- a/src/graph/visitor/PrunePropertiesVisitor.cpp +++ b/src/graph/visitor/PrunePropertiesVisitor.cpp @@ -20,17 +20,28 @@ void PrunePropertiesVisitor::visit(PlanNode *node) { } void PrunePropertiesVisitor::visit(Filter *node) { + visitCurrent(node); // Filter will use properties in filter expression + status_ = depsPruneProperties(node->dependencies()); +} + +void PrunePropertiesVisitor::visitCurrent(Filter *node) { if (node->condition() != nullptr) { status_ = extractPropsFromExpr(node->condition()); if (!status_.ok()) { return; } } +} +void PrunePropertiesVisitor::visit(Project *node) { + visitCurrent(node); // Project won't use properties in column expression status_ = depsPruneProperties(node->dependencies()); } -void PrunePropertiesVisitor::visit(Project *node) { +void PrunePropertiesVisitor::visitCurrent(Project *node) { + // TODO won't use properties of not-root Project + // bool used = used_; + used_ = false; if (node->columns()) { const auto &columns = node->columns()->columns(); auto &colNames = node->colNames(); @@ -75,11 +86,14 @@ void PrunePropertiesVisitor::visit(Project *node) { } } } +} +void PrunePropertiesVisitor::visit(Aggregate *node) { + visitCurrent(node); status_ = depsPruneProperties(node->dependencies()); } -void PrunePropertiesVisitor::visit(Aggregate *node) { +void PrunePropertiesVisitor::visitCurrent(Aggregate *node) { for (auto *groupKey : node->groupKeys()) { status_ = extractPropsFromExpr(groupKey); if (!status_.ok()) { @@ -92,10 +106,16 @@ void PrunePropertiesVisitor::visit(Aggregate *node) { return; } } - status_ = depsPruneProperties(node->dependencies()); } void PrunePropertiesVisitor::visit(Traverse *node) { + visitCurrent(node); + status_ = depsPruneProperties(node->dependencies()); +} + +void PrunePropertiesVisitor::visitCurrent(Traverse *node) { + bool used = used_; + used_ = false; auto &colNames = node->colNames(); DCHECK_GE(colNames.size(), 2); auto &nodeAlias = colNames[colNames.size() - 2]; @@ -115,6 +135,38 @@ void PrunePropertiesVisitor::visit(Traverse *node) { } } + if (used) { + // All properties will be used + const auto *vertexProps = node->vertexProps(); + if (vertexProps != nullptr) { + for (const auto &vertexProp : *vertexProps) { + auto tagId = vertexProp.tag_ref().value(); + auto &props = vertexProp.props_ref().value(); + for (const auto &prop : props) { + propsUsed_.vertexPropsMap[nodeAlias][tagId].emplace(prop); + } + } + } + const auto *edgeProps = node->edgeProps(); + if (edgeProps != nullptr) { + for (const auto &edgeProp : *edgeProps) { + auto edgeType = edgeProp.type_ref().value(); + auto &props = edgeProp.props_ref().value(); + for (const auto &prop : props) { + propsUsed_.edgePropsMap[edgeAlias][edgeType].emplace(prop); + } + } + } + } else { + pruneCurrent(node); + } +} + +void PrunePropertiesVisitor::pruneCurrent(Traverse *node) { + auto &colNames = node->colNames(); + DCHECK_GE(colNames.size(), 2); + auto &nodeAlias = colNames[colNames.size() - 2]; + auto &edgeAlias = colNames.back(); auto *vertexProps = node->vertexProps(); if (propsUsed_.colsSet.find(nodeAlias) == propsUsed_.colsSet.end() && vertexProps != nullptr) { auto it2 = propsUsed_.vertexPropsMap.find(nodeAlias); @@ -125,7 +177,6 @@ void PrunePropertiesVisitor::visit(Traverse *node) { auto &usedVertexProps = it2->second; if (usedVertexProps.empty()) { node->setVertexProps(nullptr); - status_ = depsPruneProperties(node->dependencies()); return; } prunedVertexProps->reserve(usedVertexProps.size()); @@ -189,19 +240,23 @@ void PrunePropertiesVisitor::visit(Traverse *node) { } node->setEdgeProps(std::move(prunedEdgeProps)); } - - status_ = depsPruneProperties(node->dependencies()); } // AppendVertices should be deleted when no properties it pulls are used by the parent node. void PrunePropertiesVisitor::visit(AppendVertices *node) { + visitCurrent(node); + status_ = depsPruneProperties(node->dependencies()); +} + +void PrunePropertiesVisitor::visitCurrent(AppendVertices *node) { + bool used = used_; + used_ = false; auto &colNames = node->colNames(); DCHECK(!colNames.empty()); auto &nodeAlias = colNames.back(); auto it = propsUsed_.colsSet.find(nodeAlias); if (it != propsUsed_.colsSet.end()) { // All properties are used // propsUsed_.colsSet.erase(it); - status_ = depsPruneProperties(node->dependencies()); return; } @@ -211,6 +266,27 @@ void PrunePropertiesVisitor::visit(AppendVertices *node) { return; } } + if (used) { + // All properties will be used + auto *vertexProps = node->props(); + if (vertexProps != nullptr) { + for (const auto &vertexProp : *vertexProps) { + auto tagId = vertexProp.tag_ref().value(); + auto &props = vertexProp.props_ref().value(); + for (const auto &prop : props) { + propsUsed_.vertexPropsMap[nodeAlias][tagId].emplace(prop); + } + } + } + } else { + pruneCurrent(node); + } +} + +void PrunePropertiesVisitor::pruneCurrent(AppendVertices *node) { + auto &colNames = node->colNames(); + DCHECK(!colNames.empty()); + auto &nodeAlias = colNames.back(); auto *vertexProps = node->props(); if (vertexProps != nullptr) { auto prunedVertexProps = std::make_unique>(); @@ -219,7 +295,6 @@ void PrunePropertiesVisitor::visit(AppendVertices *node) { auto &usedVertexProps = it2->second; if (usedVertexProps.empty()) { node->markDeleted(); - status_ = depsPruneProperties(node->dependencies()); return; } prunedVertexProps->reserve(usedVertexProps.size()); @@ -243,16 +318,18 @@ void PrunePropertiesVisitor::visit(AppendVertices *node) { } } else { node->markDeleted(); - status_ = depsPruneProperties(node->dependencies()); return; } node->setVertexProps(std::move(prunedVertexProps)); } +} +void PrunePropertiesVisitor::visit(BiJoin *node) { + visitCurrent(node); status_ = depsPruneProperties(node->dependencies()); } -void PrunePropertiesVisitor::visit(BiJoin *node) { +void PrunePropertiesVisitor::visitCurrent(BiJoin *node) { for (auto *hashKey : node->hashKeys()) { status_ = extractPropsFromExpr(hashKey); if (!status_.ok()) { @@ -265,7 +342,6 @@ void PrunePropertiesVisitor::visit(BiJoin *node) { return; } } - status_ = depsPruneProperties(node->dependencies()); } Status PrunePropertiesVisitor::depsPruneProperties(std::vector &dependencies) { diff --git a/src/graph/visitor/PrunePropertiesVisitor.h b/src/graph/visitor/PrunePropertiesVisitor.h index a0a04c8ee50..c6f67e18518 100644 --- a/src/graph/visitor/PrunePropertiesVisitor.h +++ b/src/graph/visitor/PrunePropertiesVisitor.h @@ -29,12 +29,43 @@ class PrunePropertiesVisitor final : public PlanNodeVisitor { } void visit(PlanNode *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + // void visitCurrent(PlanNode *node, bool used = false); + void visit(Filter *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(Filter *node); + void visit(Project *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(Project *node); + void visit(Aggregate *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(Aggregate *node); + void visit(Traverse *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(Traverse *node); + // prune properties in Traverse according to the used properties collected previous + void pruneCurrent(Traverse *node); + void visit(AppendVertices *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(AppendVertices *node); + // prune properties in AppendVertices according to the used properties collected previous + void pruneCurrent(AppendVertices *node); + void visit(BiJoin *node) override; + // \param node, the current node to visit + // \param used, whether properties in current node are used + void visitCurrent(BiJoin *node); private: Status depsPruneProperties(std::vector &dependencies); @@ -44,6 +75,8 @@ class PrunePropertiesVisitor final : public PlanNodeVisitor { QueryContext *qctx_; GraphSpaceID spaceID_; Status status_; + // force use all properties in current node, e.g. the root node in plan + bool used_{true}; }; } // namespace graph