diff --git a/src/graph/optimizer/rule/PushEFilterDownRule.cpp b/src/graph/optimizer/rule/PushEFilterDownRule.cpp index 3b5df8904d2..0af06f4a4b3 100644 --- a/src/graph/optimizer/rule/PushEFilterDownRule.cpp +++ b/src/graph/optimizer/rule/PushEFilterDownRule.cpp @@ -53,8 +53,12 @@ StatusOr PushEFilterDownRule::transform( auto pool = qctx->objPool(); auto eFilter = traverse->eFilter()->clone(); - eFilter = rewriteStarEdge( - eFilter, traverse->space(), *DCHECK_NOTNULL(traverse->edgeProps()), qctx->schemaMng(), pool); + eFilter = rewriteStarEdge(eFilter, + traverse->space(), + *DCHECK_NOTNULL(traverse->edgeProps()), + qctx->schemaMng(), + traverse->edgeDirection() == storage::cpp2::EdgeDirection::BOTH, + pool); if (eFilter == nullptr) { return TransformResult::noTransform(); } @@ -93,6 +97,7 @@ std::string PushEFilterDownRule::toString() const { GraphSpaceID spaceId, const std::vector &edges, meta::SchemaManager *schemaMng, + bool isBothDirection, ObjectPool *pool) { graph::RewriteVisitor::Matcher matcher = [](const Expression *exp) -> bool { switch (exp->kind()) { @@ -113,12 +118,12 @@ std::string PushEFilterDownRule::toString() const { } }; graph::RewriteVisitor::Rewriter rewriter = - [spaceId, &edges, schemaMng, pool](const Expression *exp) -> Expression * { + [spaceId, &edges, schemaMng, isBothDirection, pool](const Expression *exp) -> Expression * { auto *propertyExpr = static_cast(exp); DCHECK_EQ(propertyExpr->sym(), "*"); DCHECK(!edges.empty()); Expression *ret = nullptr; - if (edges.size() == 1) { + if (edges.size() == 1 || (isBothDirection && edges.size() == 2)) { ret = rewriteStarEdge(propertyExpr, spaceId, edges.front(), schemaMng, pool); if (ret == nullptr) { return nullptr; @@ -126,6 +131,9 @@ std::string PushEFilterDownRule::toString() const { } else { auto args = ArgumentList::make(pool); for (auto &edge : edges) { + if (isBothDirection && edge.get_type() < 0) { + continue; + } auto reEdgeExp = rewriteStarEdge(propertyExpr, spaceId, edge, schemaMng, pool); if (reEdgeExp == nullptr) { return nullptr; @@ -144,7 +152,7 @@ std::string PushEFilterDownRule::toString() const { const storage::cpp2::EdgeProp &edge, meta::SchemaManager *schemaMng, ObjectPool *pool) { - auto edgeNameResult = schemaMng->toEdgeName(spaceId, edge.get_type()); + auto edgeNameResult = schemaMng->toEdgeName(spaceId, std::abs(edge.get_type())); if (!edgeNameResult.ok()) { return nullptr; } diff --git a/src/graph/optimizer/rule/PushEFilterDownRule.h b/src/graph/optimizer/rule/PushEFilterDownRule.h index cb2b415d738..4add56e8ef3 100644 --- a/src/graph/optimizer/rule/PushEFilterDownRule.h +++ b/src/graph/optimizer/rule/PushEFilterDownRule.h @@ -26,6 +26,7 @@ class PushEFilterDownRule final : public OptRule { GraphSpaceID spaceId, const std::vector &edges, meta::SchemaManager *schemaMng, + bool isBothDirection, ObjectPool *pool); static Expression *rewriteStarEdge(const PropertyExpression *exp, GraphSpaceID spaceId, diff --git a/tests/tck/features/optimizer/PushEFilterDownRule.feature b/tests/tck/features/optimizer/PushEFilterDownRule.feature index 96637782021..7366594663c 100644 --- a/tests/tck/features/optimizer/PushEFilterDownRule.feature +++ b/tests/tck/features/optimizer/PushEFilterDownRule.feature @@ -25,6 +25,34 @@ Feature: Push EFilter down rule | 8 | Traverse | 7 | {"edge filter": "", "filter": "(like.likeness==95)"} | | 7 | IndexScan | 0 | | | 0 | Start | | | + When profiling query: + """ + MATCH (v:player{name: 'Tim Duncan'})<-[e:like{likeness: 95}]-() return v.player.name AS name + """ + Then the result should be, in any order: + | name | + | "Tim Duncan" | + And the execution plan should be: + | id | name | dependencies | operator info | + | 5 | Project | 8 | | + | 8 | Traverse | 7 | {"edge filter": "", "filter": "(like.likeness==95)"} | + | 7 | IndexScan | 0 | | + | 0 | Start | | | + When profiling query: + """ + MATCH (v:player{name: 'Tim Duncan'})-[e:like|serve{likeness: 95}]-() return v.player.name AS name + """ + Then the result should be, in any order: + | name | + | "Tim Duncan" | + | "Tim Duncan" | + | "Tim Duncan" | + And the execution plan should be: + | id | name | dependencies | operator info | + | 5 | Project | 8 | | + | 8 | Traverse | 7 | {"edge filter": "", "filter": "(_any(like.likeness,serve.likeness)==95)"} | + | 7 | IndexScan | 0 | | + | 0 | Start | | | When profiling query: """ MATCH (v:player{name: 'Tim Duncan'})-[e:like*1..2{likeness: 95}]->() return v.player.name AS name diff --git a/tests/tck/features/optimizer/PushFilterDownHashInnerJoinRule.feature b/tests/tck/features/optimizer/PushFilterDownHashInnerJoinRule.feature index e7c09c3b2d8..0fcdd16ade2 100644 --- a/tests/tck/features/optimizer/PushFilterDownHashInnerJoinRule.feature +++ b/tests/tck/features/optimizer/PushFilterDownHashInnerJoinRule.feature @@ -32,19 +32,19 @@ Feature: Push Filter down HashInnerJoin rule | [:like "Tony Parker"->"Tim Duncan" @0 {likeness: 95}] | ("Tony Parker" :player{age: 36, name: "Tony Parker"}) | | [:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}] | ("Tony Parker" :player{age: 36, name: "Tony Parker"}) | And the execution plan should be: - | id | name | dependencies | operator info | - | 30 | Sort | 14 | | - | 14 | Project | 19 | | - | 19 | HashInnerJoin | 6,22 | | - | 6 | Project | 20 | | - | 20 | AppendVertices | 2 | | - | 2 | Dedup | 1 | | - | 1 | PassThrough | 3 | | - | 3 | Start | | | - | 22 | Project | 10 | | - | 10 | AppendVertices | 9 | | - | 9 | Traverse | 7 | {"edge filter": "(*.likeness>0)"} | - | 7 | Argument | | | + | id | name | dependencies | operator info | + | 30 | Sort | 14 | | + | 14 | Project | 19 | | + | 19 | HashInnerJoin | 6,22 | | + | 6 | Project | 20 | | + | 20 | AppendVertices | 2 | | + | 2 | Dedup | 1 | | + | 1 | PassThrough | 3 | | + | 3 | Start | | | + | 22 | Project | 10 | | + | 10 | AppendVertices | 9 | | + | 9 | Traverse | 7 | {"filter": "(like.likeness>0)"} | + | 7 | Argument | | | When profiling query: """ MATCH (v:player) @@ -122,7 +122,7 @@ Feature: Push Filter down HashInnerJoin rule | 3 | Start | | | | 25 | Project | 10 | | | 10 | AppendVertices | 9 | | - | 9 | Traverse | 7 | {"edge filter": "(*.likeness>0)"} | + | 9 | Traverse | 7 | {"filter": "(like.likeness>0)"} | | 7 | Argument | | | When profiling query: """