From 1a194f1608639e28244623e1327c19853b572d86 Mon Sep 17 00:00:00 2001 From: jievince <38901892+jievince@users.noreply.github.com> Date: Sat, 3 Dec 2022 17:43:36 +0800 Subject: [PATCH 1/4] remove useless appendVertices below innner/left join --- src/common/expression/PredicateExpression.cpp | 9 ++-- src/graph/optimizer/CMakeLists.txt | 2 +- ... => RemoveAppendVerticesBelowJoinRule.cpp} | 52 ++++++++++--------- ....h => RemoveAppendVerticesBelowJoinRule.h} | 8 +-- ...RemoveAppendVerticesBelowJoinRule.feature} | 34 +++++++++++- 5 files changed, 71 insertions(+), 34 deletions(-) rename src/graph/optimizer/rule/{OptimizeLeftJoinPredicateRule.cpp => RemoveAppendVerticesBelowJoinRule.cpp} (73%) rename src/graph/optimizer/rule/{OptimizeLeftJoinPredicateRule.h => RemoveAppendVerticesBelowJoinRule.h} (83%) rename tests/tck/features/optimizer/{OptimizeLeftJoinPredicateRule.feature => RemoveAppendVerticesBelowJoinRule.feature} (68%) diff --git a/src/common/expression/PredicateExpression.cpp b/src/common/expression/PredicateExpression.cpp index 88f71a058c4..d2ede313a12 100644 --- a/src/common/expression/PredicateExpression.cpp +++ b/src/common/expression/PredicateExpression.cpp @@ -19,11 +19,14 @@ std::unordered_map PredicateExpression:: const Value& PredicateExpression::evalExists(ExpressionContext& ctx) { DCHECK(collection_->kind() == Expression::Kind::kAttribute || collection_->kind() == Expression::Kind::kSubscript || - collection_->kind() == Expression::Kind::kLabelTagProperty) + collection_->kind() == Expression::Kind::kLabelTagProperty || + collection_->kind() == Expression::Kind::kTagProperty) << "actual kind: " << collection_->kind() << ", toString: " << toString(); - if (collection_->kind() == Expression::Kind::kLabelTagProperty) { - result_ = !collection_->eval(ctx).isNull(); + if (collection_->kind() == Expression::Kind::kLabelTagProperty || + collection_->kind() == Expression::Kind::kTagProperty) { + auto v = collection_->eval(ctx); + result_ = (!v.isNull()) && (!v.empty()); return result_; } diff --git a/src/graph/optimizer/CMakeLists.txt b/src/graph/optimizer/CMakeLists.txt index b3c17f8427c..b99c495d16c 100644 --- a/src/graph/optimizer/CMakeLists.txt +++ b/src/graph/optimizer/CMakeLists.txt @@ -55,7 +55,7 @@ nebula_add_library( rule/PushLimitDownScanEdgesRule.cpp rule/RemoveProjectDedupBeforeGetDstBySrcRule.cpp rule/PushFilterDownTraverseRule.cpp - rule/OptimizeLeftJoinPredicateRule.cpp + rule/RemoveAppendVerticesBelowJoinRule.cpp ) nebula_add_subdirectory(test) diff --git a/src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.cpp b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp similarity index 73% rename from src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.cpp rename to src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp index d9af805ae24..fe9b5bfe26f 100644 --- a/src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.cpp +++ b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp @@ -2,7 +2,7 @@ // // This source code is licensed under Apache 2.0 License. -#include "graph/optimizer/rule/OptimizeLeftJoinPredicateRule.h" +#include "graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.h" #include "graph/optimizer/OptContext.h" #include "graph/optimizer/OptGroup.h" @@ -16,16 +16,16 @@ using nebula::graph::QueryContext; namespace nebula { namespace opt { -std::unique_ptr OptimizeLeftJoinPredicateRule::kInstance = - std::unique_ptr(new OptimizeLeftJoinPredicateRule()); +std::unique_ptr RemoveAppendVerticesBelowJoinRule::kInstance = + std::unique_ptr(new RemoveAppendVerticesBelowJoinRule()); -OptimizeLeftJoinPredicateRule::OptimizeLeftJoinPredicateRule() { +RemoveAppendVerticesBelowJoinRule::RemoveAppendVerticesBelowJoinRule() { RuleSet::QueryRules().addRule(this); } -const Pattern& OptimizeLeftJoinPredicateRule::pattern() const { +const Pattern& RemoveAppendVerticesBelowJoinRule::pattern() const { static Pattern pattern = Pattern::create( - PlanNode::Kind::kHashLeftJoin, + {PlanNode::Kind::kHashLeftJoin, PlanNode::Kind::kHashInnerJoin}, {Pattern::create(PlanNode::Kind::kUnknown), Pattern::create(PlanNode::Kind::kProject, {Pattern::create(PlanNode::Kind::kAppendVertices, @@ -33,11 +33,11 @@ const Pattern& OptimizeLeftJoinPredicateRule::pattern() const { return pattern; } -StatusOr OptimizeLeftJoinPredicateRule::transform( +StatusOr RemoveAppendVerticesBelowJoinRule::transform( OptContext* octx, const MatchedResult& matched) const { - auto* leftJoinGroupNode = matched.node; - auto* leftJoinGroup = leftJoinGroupNode->group(); - auto* leftJoin = static_cast(leftJoinGroupNode->node()); + auto* joinGroupNode = matched.node; + auto* joinGroup = joinGroupNode->group(); + auto* join = static_cast(joinGroupNode->node()); auto* projectGroupNode = matched.dependencies[1].node; auto* project = static_cast(projectGroupNode->node()); @@ -53,8 +53,8 @@ StatusOr OptimizeLeftJoinPredicateRule::transform( auto& tvEdgeAlias = traverse->edgeAlias(); - auto& leftExprs = leftJoin->hashKeys(); - auto& rightExprs = leftJoin->probeKeys(); + auto& leftExprs = join->hashKeys(); + auto& rightExprs = join->probeKeys(); bool found = false; size_t rightExprIdx = 0; @@ -111,7 +111,7 @@ StatusOr OptimizeLeftJoinPredicateRule::transform( auto* pool = octx->qctx()->objPool(); // Let the new project generate expr `none_direct_dst($-.tvEdgeAlias)`, - // and let the new left join use it as right expr + // and let the new left/inner join use it as right expr auto* args = ArgumentList::make(pool); args->addArgument(InputPropertyExpression::make(pool, tvEdgeAlias)); auto* newPrjExpr = FunctionCallExpression::make(pool, "none_direct_dst", args); @@ -137,8 +137,12 @@ StatusOr OptimizeLeftJoinPredicateRule::transform( newRightExprs.emplace_back(rightExprs[i]->clone()); } } - auto* newLeftJoin = - graph::HashLeftJoin::make(octx->qctx(), nullptr, nullptr, leftExprs, newRightExprs); + graph::HashJoin* newJoin = nullptr; + if (join->kind() == PlanNode::Kind::kHashLeftJoin) { + newJoin = graph::HashLeftJoin::make(octx->qctx(), nullptr, nullptr, leftExprs, newRightExprs); + } else { + newJoin = graph::HashInnerJoin::make(octx->qctx(), nullptr, nullptr, leftExprs, newRightExprs); + } TransformResult result; result.eraseAll = true; @@ -148,19 +152,19 @@ StatusOr OptimizeLeftJoinPredicateRule::transform( auto* newProjectGroupNode = newProjectGroup->makeGroupNode(newProject); newProjectGroupNode->setDeps(appendVerticesGroupNode->dependencies()); - newLeftJoin->setLeftVar(leftJoin->leftInputVar()); - newLeftJoin->setRightVar(newProject->outputVar()); - newLeftJoin->setOutputVar(leftJoin->outputVar()); - auto* newLeftJoinGroupNode = OptGroupNode::create(octx, newLeftJoin, leftJoinGroup); - newLeftJoinGroupNode->dependsOn(leftJoinGroupNode->dependencies()[0]); - newLeftJoinGroupNode->dependsOn(newProjectGroup); + newJoin->setLeftVar(join->leftInputVar()); + newJoin->setRightVar(newProject->outputVar()); + newJoin->setOutputVar(join->outputVar()); + auto* newJoinGroupNode = OptGroupNode::create(octx, newJoin, joinGroup); + newJoinGroupNode->dependsOn(joinGroupNode->dependencies()[0]); + newJoinGroupNode->dependsOn(newProjectGroup); - result.newGroupNodes.emplace_back(newLeftJoinGroupNode); + result.newGroupNodes.emplace_back(newJoinGroupNode); return result; } -std::string OptimizeLeftJoinPredicateRule::toString() const { - return "OptimizeLeftJoinPredicateRule"; +std::string RemoveAppendVerticesBelowJoinRule::toString() const { + return "RemoveAppendVerticesBelowJoinRule"; } } // namespace opt diff --git a/src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.h b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.h similarity index 83% rename from src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.h rename to src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.h index ef27924af2e..d955ca58950 100644 --- a/src/graph/optimizer/rule/OptimizeLeftJoinPredicateRule.h +++ b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.h @@ -10,7 +10,7 @@ namespace nebula { namespace opt { // Before: -// HashLeftJoin({id(v)}, {id(v)}) +// HashLeft/InnerJoin({id(v)}, {id(v)}) // | | // ... Project // | | @@ -19,7 +19,7 @@ namespace opt { // ... Traverse(e) // // After: -// HashLeftJoin({id(v)}, {$-.v}) +// HashLeft/InnerJoin({id(v)}, {$-.v}) // | | // ... Project(..., none_direct_dst(e) AS v) // | | @@ -27,7 +27,7 @@ namespace opt { // | // ... // -class OptimizeLeftJoinPredicateRule final : public OptRule { +class RemoveAppendVerticesBelowJoinRule final : public OptRule { public: const Pattern &pattern() const override; @@ -37,7 +37,7 @@ class OptimizeLeftJoinPredicateRule final : public OptRule { std::string toString() const override; private: - OptimizeLeftJoinPredicateRule(); + RemoveAppendVerticesBelowJoinRule(); static std::unique_ptr kInstance; }; diff --git a/tests/tck/features/optimizer/OptimizeLeftJoinPredicateRule.feature b/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature similarity index 68% rename from tests/tck/features/optimizer/OptimizeLeftJoinPredicateRule.feature rename to tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature index ab6fbe9e736..28773fbb485 100644 --- a/tests/tck/features/optimizer/OptimizeLeftJoinPredicateRule.feature +++ b/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature @@ -1,12 +1,13 @@ # Copyright (c) 2022 vesoft inc. All rights reserved. # # This source code is licensed under Apache 2.0 License. -Feature: Optimize left join predicate +@jie +Feature: Remove AppendVertices Below Join Background: Given a graph with space named "nba" - Scenario: optimize left join predicate + Scenario: Remove AppendVertices below left join When profiling query: """ MATCH (person:player)-[:like*1..2]-(friend:player)-[:serve]->(friendTeam:team) @@ -62,3 +63,32 @@ Feature: Optimize left join predicate | 14 | Traverse | 12 | | | 12 | Traverse | 11 | | | 11 | Argument | | | + + Scenario: Remove AppendVertices below inner join + When profiling query: + """ + MATCH (me:player)-[:like]->(both) + WHERE id(me) == "Tony Parker" + MATCH (he:player)-[:like]->(both) + WHERE id(he) == "Tim Duncan" + RETURN * + """ + Then the result should be, in order, with relax comparison: + | me | both | he | + | ("Tony Parker") | ("Manu Ginobili") | ("Tim Duncan") | + And the execution plan should be: + | id | name | dependencies | operator info | + | 16 | HashInnerJoin | 10,15 | {"hashKeys": ["_joinkey($-.both)"], "probeKeys": ["$-.both"]} | + | 10 | Dedup | 28 | | + | 28 | Project | 22 | | + | 22 | Filter | 26 | | + | 26 | AppendVertices | 25 | | + | 25 | Traverse | 24 | | + | 24 | Traverse | 2 | | + | 2 | Dedup | 1 | | + | 1 | PassThrough | 3 | | + | 3 | Start | | | + | 15 | Project | 14 | {"columns": ["$-.he AS he", "none_direct_dst($-.__VAR_1) AS v"]} | + | 14 | Traverse | 12 | | + | 12 | Traverse | 11 | | + | 11 | Argument | | | From b8bbb043d41f7283b6a5c1a3c7aee26903d42b23 Mon Sep 17 00:00:00 2001 From: jievince <38901892+jievince@users.noreply.github.com> Date: Wed, 7 Dec 2022 12:35:44 +0800 Subject: [PATCH 2/4] fix tck --- .../RemoveAppendVerticesBelowJoinRule.feature | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature b/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature index 28773fbb485..2d767926e47 100644 --- a/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature +++ b/tests/tck/features/optimizer/RemoveAppendVerticesBelowJoinRule.feature @@ -1,7 +1,6 @@ # Copyright (c) 2022 vesoft inc. All rights reserved. # # This source code is licensed under Apache 2.0 License. -@jie Feature: Remove AppendVertices Below Join Background: @@ -16,10 +15,10 @@ Feature: Remove AppendVertices Below Join OPTIONAL MATCH (friend)<-[:like]-(friend2:player)<-[:like]-(friendTeam) WITH friendTeam, count(friend2) AS numFriends RETURN - id(friendTeam) AS teamId, - friendTeam.team.name AS teamName, - numFriends - ORDER BY teamName DESC + id(friendTeam) AS teamId, + friendTeam.team.name AS teamName, + numFriends + ORDER BY teamName DESC """ Then the result should be, in order, with relax comparison: | teamId | teamName | numFriends | @@ -77,18 +76,16 @@ Feature: Remove AppendVertices Below Join | me | both | he | | ("Tony Parker") | ("Manu Ginobili") | ("Tim Duncan") | And the execution plan should be: - | id | name | dependencies | operator info | - | 16 | HashInnerJoin | 10,15 | {"hashKeys": ["_joinkey($-.both)"], "probeKeys": ["$-.both"]} | - | 10 | Dedup | 28 | | - | 28 | Project | 22 | | - | 22 | Filter | 26 | | - | 26 | AppendVertices | 25 | | - | 25 | Traverse | 24 | | - | 24 | Traverse | 2 | | - | 2 | Dedup | 1 | | - | 1 | PassThrough | 3 | | - | 3 | Start | | | - | 15 | Project | 14 | {"columns": ["$-.he AS he", "none_direct_dst($-.__VAR_1) AS v"]} | - | 14 | Traverse | 12 | | - | 12 | Traverse | 11 | | - | 11 | Argument | | | + | id | name | dependencies | operator info | + | 13 | HashInnerJoin | 6,12 | {"hashKeys": ["_joinkey($-.both)"], "probeKeys": ["$-.both"]} | + | 6 | Project | 5 | | + | 5 | AppendVertices | 15 | | + | 15 | Traverse | 2 | | + | 2 | Dedup | 1 | | + | 1 | PassThrough | 3 | | + | 3 | Start | | | + | 12 | Project | 16 | {"columns": ["$-.he AS he", "none_direct_dst($-.__VAR_1) AS both"]} | + | 16 | Traverse | 8 | | + | 8 | Dedup | 7 | | + | 7 | PassThrough | 9 | | + | 9 | Start | | | From 767cb3fe6e7d8a10d14a56ee9f836aa200610e78 Mon Sep 17 00:00:00 2001 From: jievince <38901892+jievince@users.noreply.github.com> Date: Wed, 7 Dec 2022 12:59:39 +0800 Subject: [PATCH 3/4] fix tck --- .../features/match/MultiQueryParts.feature | 19 +++++++------ .../optimizer/PrunePropertiesRule.feature | 27 +++++++++---------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/tests/tck/features/match/MultiQueryParts.feature b/tests/tck/features/match/MultiQueryParts.feature index c51338e321b..4cb98264889 100644 --- a/tests/tck/features/match/MultiQueryParts.feature +++ b/tests/tck/features/match/MultiQueryParts.feature @@ -147,14 +147,14 @@ Feature: Multi Query Parts MATCH (v3:player)-[:like]->(v1)<-[e5]-(v4) where id(v3) == "Tim Duncan" return * """ Then the result should be, in any order, with relax comparison: - | v1 | v2 | e3 | v4 | v3 | e5 | - | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Tim Duncan" @0 {likeness: 95}] | ("Tim Duncan") | ("Tim Duncan") | [:teammate "Tim Duncan"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Manu Ginobili") | [:like "Manu Ginobili"->"Tim Duncan" @0 {likeness: 90}] | ("Tim Duncan") | ("Tim Duncan") | [:teammate "Tim Duncan"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Tim Duncan" ) | [:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Tim Duncan" ) | [:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0 {}] | - | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"LaMarcus Aldridge" @0 {likeness: 90}] | ("LaMarcus Aldridge") | ("Tim Duncan") | [:like "LaMarcus Aldridge"->"Tony Parker" @0 {}] | + | v1 | v2 | e3 | v4 | v3 | e5 | + | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Tim Duncan" @0 {likeness: 95}] | ("Tim Duncan") | ("Tim Duncan") | [:teammate "Tim Duncan"->"Tony Parker" @0] | + | ("Tony Parker") | ("Manu Ginobili") | [:like "Manu Ginobili"->"Tim Duncan" @0 {likeness: 90}] | ("Tim Duncan") | ("Tim Duncan") | [:teammate "Tim Duncan"->"Tony Parker" @0] | + | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0] | + | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0] | + | ("Tony Parker") | ("Tim Duncan" ) | [:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0] | + | ("Tony Parker") | ("Tim Duncan" ) | [:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}] | ("Manu Ginobili") | ("Tim Duncan") | [:teammate "Manu Ginobili"->"Tony Parker" @0] | + | ("Tony Parker") | ("Tony Parker") | [:like "Tony Parker"->"LaMarcus Aldridge" @0 {likeness: 90}] | ("LaMarcus Aldridge") | ("Tim Duncan") | [:like "LaMarcus Aldridge"->"Tony Parker" @0] | # The redudant Project after HashInnerJoin is removed now And the execution plan should be: | id | name | dependencies | profiling data | operator info | @@ -166,8 +166,7 @@ Feature: Multi Query Parts | 2 | Dedup | 1 | | | | 1 | PassThrough | 3 | | | | 3 | Start | | | | - | 14 | Project | 13 | | | - | 13 | AppendVertices | 12 | | | + | 14 | Project | 12 | | | | 12 | Traverse | 21 | | | | 21 | Traverse | 9 | | | | 9 | Dedup | 8 | | | diff --git a/tests/tck/features/optimizer/PrunePropertiesRule.feature b/tests/tck/features/optimizer/PrunePropertiesRule.feature index 32a3af6a01f..5438220bdf0 100644 --- a/tests/tck/features/optimizer/PrunePropertiesRule.feature +++ b/tests/tck/features/optimizer/PrunePropertiesRule.feature @@ -364,8 +364,7 @@ Feature: Prune Properties rule | 11 | Project | 10 | | | 10 | AppendVertices | 9 | { "props": "[{\"props\":[\"name\", \"age\", \"_tag\"],\"tagId\":9}, {\"props\":[\"name\", \"speciality\", \"_tag\"],\"tagId\":8}, {\"props\":[\"name\", \"_tag\"],\"tagId\":10}]" } | | 9 | Traverse | 8 | { "vertexProps": "[{\"props\":[\"name\"],\"tagId\":9}]" } | - | 8 | Argument | 0 | | - | 0 | Start | | | + | 8 | Argument | | | When profiling query: """ MATCH (m:player{name:"Tim Duncan"})-[:like]-(n)--() @@ -377,19 +376,17 @@ Feature: Prune Properties rule | scount | | 270 | And the execution plan should be: - | id | name | dependencies | operator info | - | 12 | Aggregate | 13 | | - | 13 | HashInnerJoin | 15, 11 | | - | 15 | Project | 4 | | - | 4 | Traverse | 3 | { "vertexProps": "" } | - | 3 | Traverse | 14 | { "vertexProps": "" } | - | 14 | IndexScan | 2 | | - | 2 | Start | | | - | 11 | Project | 10 | | - | 10 | AppendVertices | 9 | { "props": "[{\"props\":[\"_tag\"],\"tagId\":8}, {\"props\":[\"_tag\"],\"tagId\":9}, {\"props\":[\"_tag\"],\"tagId\":10}]" } | - | 9 | Traverse | 8 | { "vertexProps": "" } | - | 8 | Argument | 0 | | - | 0 | Start | | | + | id | name | dependencies | operator info | + | 12 | Aggregate | 13 | | + | 13 | HashInnerJoin | 15, 11 | | + | 15 | Project | 4 | | + | 4 | Traverse | 3 | { "vertexProps": "" } | + | 3 | Traverse | 14 | { "vertexProps": "" } | + | 14 | IndexScan | 2 | | + | 2 | Start | | | + | 11 | Project | 9 | | + | 9 | Traverse | 8 | { "vertexProps": "" } | + | 8 | Argument | | | @distonly Scenario: return function From e844cf8b36feaf0cf7a3ac9bb155ec4f0f509f94 Mon Sep 17 00:00:00 2001 From: jievince <38901892+jievince@users.noreply.github.com> Date: Wed, 7 Dec 2022 13:30:11 +0800 Subject: [PATCH 4/4] fix tck --- .../RemoveAppendVerticesBelowJoinRule.cpp | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp index fe9b5bfe26f..5b0364b7dfd 100644 --- a/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp +++ b/src/graph/optimizer/rule/RemoveAppendVerticesBelowJoinRule.cpp @@ -56,6 +56,23 @@ StatusOr RemoveAppendVerticesBelowJoinRule::transform( auto& leftExprs = join->hashKeys(); auto& rightExprs = join->probeKeys(); + std::vector referAVNodeAliasExprs; + for (auto* rightExpr : rightExprs) { + auto propExprs = graph::ExpressionUtils::collectAll( + rightExpr, {Expression::Kind::kVarProperty, Expression::Kind::kInputProperty}); + for (auto* expr : propExprs) { + auto* propExpr = static_cast(expr); + if (propExpr->prop() == avNodeAlias) { + referAVNodeAliasExprs.push_back(propExpr); + } + } + } + // If avNodeAlias is referred by more than one expr, + // we cannot remove the append vertices which generate the avNodeAlias column + if (referAVNodeAliasExprs.size() > 1) { + return TransformResult::noTransform(); + } + bool found = false; size_t rightExprIdx = 0; for (size_t i = 0; i < rightExprs.size(); ++i) { @@ -89,11 +106,28 @@ StatusOr RemoveAppendVerticesBelowJoinRule::transform( return TransformResult::noTransform(); } + auto columns = project->columns()->columns(); + referAVNodeAliasExprs.clear(); + for (auto* column : columns) { + auto propExprs = graph::ExpressionUtils::collectAll( + column->expr(), {Expression::Kind::kVarProperty, Expression::Kind::kInputProperty}); + for (auto* expr : propExprs) { + auto* propExpr = static_cast(expr); + if (propExpr->prop() == avNodeAlias) { + referAVNodeAliasExprs.push_back(propExpr); + } + } + } + // If avNodeAlias is referred by more than one expr, + // we cannot remove the append vertices which generate the avNodeAlias column + if (referAVNodeAliasExprs.size() > 1) { + return TransformResult::noTransform(); + } + found = false; size_t prjIdx = 0; - auto* columns = project->columns(); - for (size_t i = 0; i < columns->size(); ++i) { - const auto* col = columns->columns()[i]; + for (size_t i = 0; i < columns.size(); ++i) { + const auto* col = columns[i]; if (col->expr()->kind() != Expression::Kind::kInputProperty) { continue; }