From d1cb3dabae73233c834d80fed4b02dc4dcce322f Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Tue, 18 Jan 2022 17:10:28 +0800 Subject: [PATCH 01/13] fix bug --- src/graph/planner/SequentialPlanner.h | 2 ++ src/graph/validator/Validator.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.h b/src/graph/planner/SequentialPlanner.h index 656bede413e..4f60461ce04 100644 --- a/src/graph/planner/SequentialPlanner.h +++ b/src/graph/planner/SequentialPlanner.h @@ -6,6 +6,8 @@ #ifndef GRAPH_PLANNER_PLANNERS_SEQUENTIALPLANNER_H_ #define GRAPH_PLANNER_PLANNERS_SEQUENTIALPLANNER_H_ +#include + #include "graph/context/QueryContext.h" #include "graph/planner/Planner.h" diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 5aa074d892c..cc0cb44b184 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -7,7 +7,10 @@ #include +#include + #include "common/function/FunctionManager.h" +#include "graph/planner/plan/PlanNode.h" #include "graph/planner/plan/Query.h" #include "graph/util/ExpressionUtils.h" #include "graph/util/SchemaUtil.h" @@ -299,8 +302,14 @@ std::vector Validator::getOutColNames() const { Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { DCHECK(node != nullptr); DCHECK(appended != nullptr); - if (!node->isSingleInput()) { - return Status::SemanticError("%s not support to append an input.", + + std::set skipTypeSet = {PlanNode::Kind::kSwitchSpace}; + + // Note: there's check which forbids sentence like `[dql(or other) ngql];[cypher]`. + // So there's a kStart planNode in the cypher sentence of end. + // But this check is not needed for `use space` or other sentence. + if (skipTypeSet.find(appended->kind()) != skipTypeSet.end() || !node->isSingleInput()) { + return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } static_cast(node)->dependsOn(appended); From fd8e69922cc2fdd9de9bf084a59bcb636204f559 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Tue, 18 Jan 2022 17:26:27 +0800 Subject: [PATCH 02/13] add tck --- src/graph/planner/SequentialPlanner.h | 2 -- src/graph/validator/Validator.cpp | 4 +--- tests/tck/features/match/Base.feature | 10 ++++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.h b/src/graph/planner/SequentialPlanner.h index 4f60461ce04..656bede413e 100644 --- a/src/graph/planner/SequentialPlanner.h +++ b/src/graph/planner/SequentialPlanner.h @@ -6,8 +6,6 @@ #ifndef GRAPH_PLANNER_PLANNERS_SEQUENTIALPLANNER_H_ #define GRAPH_PLANNER_PLANNERS_SEQUENTIALPLANNER_H_ -#include - #include "graph/context/QueryContext.h" #include "graph/planner/Planner.h" diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index cc0cb44b184..8b6c9595fc8 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -7,8 +7,6 @@ #include -#include - #include "common/function/FunctionManager.h" #include "graph/planner/plan/PlanNode.h" #include "graph/planner/plan/Query.h" @@ -308,7 +306,7 @@ Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { // Note: there's check which forbids sentence like `[dql(or other) ngql];[cypher]`. // So there's a kStart planNode in the cypher sentence of end. // But this check is not needed for `use space` or other sentence. - if (skipTypeSet.find(appended->kind()) != skipTypeSet.end() || !node->isSingleInput()) { + if (skipTypeSet.find(appended->kind()) == skipTypeSet.end() && !node->isSingleInput()) { return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } diff --git a/tests/tck/features/match/Base.feature b/tests/tck/features/match/Base.feature index 13573b18c47..c5b99b14ad5 100644 --- a/tests/tck/features/match/Base.feature +++ b/tests/tck/features/match/Base.feature @@ -699,3 +699,13 @@ Feature: Basic match Then the result should be, in any order: | v | | ("Tim Duncan":bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) | + + Scenario: Sequential sentence + When executing query: + """ + USE nba; + MATCH (n:player) RETURN n LIMIT 1; + """ + Then the result should be, in any order: + | n | + | ("Boris Diaw" :player{age: 36, name: "Boris Diaw"}) | From 498408e5df60df8cf9c379b4b1c7f52d40ef672c Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Thu, 20 Jan 2022 14:16:04 +0800 Subject: [PATCH 03/13] remove set --- src/graph/validator/Validator.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 8b6c9595fc8..fc4d29fbae8 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -301,12 +301,10 @@ Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { DCHECK(node != nullptr); DCHECK(appended != nullptr); - std::set skipTypeSet = {PlanNode::Kind::kSwitchSpace}; - // Note: there's check which forbids sentence like `[dql(or other) ngql];[cypher]`. // So there's a kStart planNode in the cypher sentence of end. // But this check is not needed for `use space` or other sentence. - if (skipTypeSet.find(appended->kind()) == skipTypeSet.end() && !node->isSingleInput()) { + if (appended->kind() != PlanNode::Kind::kSwitchSpace && !node->isSingleInput()) { return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } From 42f5777d265d8ca076c974c8fad4336afab12253 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:30:30 +0800 Subject: [PATCH 04/13] fix --- src/graph/planner/match/MatchClausePlanner.cpp | 6 ------ src/graph/validator/Validator.cpp | 5 +---- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/graph/planner/match/MatchClausePlanner.cpp b/src/graph/planner/match/MatchClausePlanner.cpp index 3bbc1985593..fda817a224b 100644 --- a/src/graph/planner/match/MatchClausePlanner.cpp +++ b/src/graph/planner/match/MatchClausePlanner.cpp @@ -206,12 +206,6 @@ Status MatchClausePlanner::findStarts(std::vector& nodeInfos, matchClauseCtx->sentence->toString().c_str()); } - if (matchClausePlan.tail->isSingleInput()) { - auto start = StartNode::make(matchClauseCtx->qctx); - matchClausePlan.tail->setDep(0, start); - matchClausePlan.tail = start; - } - return Status::OK(); } diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index fc4d29fbae8..03f8d48867d 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -301,10 +301,7 @@ Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { DCHECK(node != nullptr); DCHECK(appended != nullptr); - // Note: there's check which forbids sentence like `[dql(or other) ngql];[cypher]`. - // So there's a kStart planNode in the cypher sentence of end. - // But this check is not needed for `use space` or other sentence. - if (appended->kind() != PlanNode::Kind::kSwitchSpace && !node->isSingleInput()) { + if (!node->isSingleInput()) { return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } From 58f285c69991740ef1dfb90bbe77a05285f62667 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:42:36 +0800 Subject: [PATCH 05/13] rm header --- src/graph/validator/Validator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 03f8d48867d..737471a29ba 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -8,7 +8,6 @@ #include #include "common/function/FunctionManager.h" -#include "graph/planner/plan/PlanNode.h" #include "graph/planner/plan/Query.h" #include "graph/util/ExpressionUtils.h" #include "graph/util/SchemaUtil.h" From 786436875eaa41eb1b4bd042f07908ad77ee4576 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 11:37:29 +0800 Subject: [PATCH 06/13] fix --- src/graph/planner/SequentialPlanner.cpp | 3 +++ src/graph/planner/plan/PlanNode.h | 4 ++++ src/graph/validator/Validator.cpp | 12 ++++++++++++ src/graph/validator/Validator.h | 3 +++ 4 files changed, 22 insertions(+) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index 9e0690f1e3f..b7c5ad7d257 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -24,6 +24,9 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { subPlan.root = validators.back()->root(); ifBuildDataCollect(subPlan, qctx); for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) { + if ((iter + 1)->get()->tail()->kind() == PlanNode::Kind::kStart) { + (iter + 1)->get()->rmLeftTailStartNode(); + } NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { diff --git a/src/graph/planner/plan/PlanNode.h b/src/graph/planner/plan/PlanNode.h index 4db19bdadf0..4948c473a3c 100644 --- a/src/graph/planner/plan/PlanNode.h +++ b/src/graph/planner/plan/PlanNode.h @@ -238,6 +238,10 @@ class PlanNode { return dependencies_; } + auto& dependencies() { + return dependencies_; + } + const PlanNode* dep(size_t index = 0) const { DCHECK_LT(index, dependencies_.size()); return dependencies_.at(index); diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 737471a29ba..0be4d4c0f58 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -312,6 +312,18 @@ Status Validator::appendPlan(PlanNode* root) { return appendPlan(tail_, root); } +void Validator::rmLeftTailStartNode() { + PlanNode* node = root_; + if (node->dependencies().size() == 0UL) return; + + while (node->dependencies()[0]->dependencies().size() > 0UL) { + node = const_cast(node->dependencies()[0]); + } + if (node->dependencies().size() == 1UL) { + node->dependencies().clear(); + } +} + Status Validator::validate() { if (!vctx_) { VLOG(1) << "Validate context was not given."; diff --git a/src/graph/validator/Validator.h b/src/graph/validator/Validator.h index b1206769fc8..514b31deb7a 100644 --- a/src/graph/validator/Validator.h +++ b/src/graph/validator/Validator.h @@ -112,6 +112,9 @@ class Validator { return sentence_; } + // remove the left tail node from the plan + void rmLeftTailStartNode(); + protected: Validator(Sentence* sentence, QueryContext* qctx); From 3d8f78892f3da7f7a085589543fd173f6d28e94e Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 11:55:32 +0800 Subject: [PATCH 07/13] remove changes in match --- src/graph/planner/SequentialPlanner.cpp | 3 - .../planner/match/MatchClausePlanner.cpp | 6 + src/graph/validator/Validator.cpp | 8 +- src/graph/validator/Validator.h | 2 +- .../match/MultiLineMultiQueryParts.feature | 272 ++++++++++++++++++ 5 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 tests/tck/features/match/MultiLineMultiQueryParts.feature diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index b7c5ad7d257..9e0690f1e3f 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -24,9 +24,6 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { subPlan.root = validators.back()->root(); ifBuildDataCollect(subPlan, qctx); for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) { - if ((iter + 1)->get()->tail()->kind() == PlanNode::Kind::kStart) { - (iter + 1)->get()->rmLeftTailStartNode(); - } NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { diff --git a/src/graph/planner/match/MatchClausePlanner.cpp b/src/graph/planner/match/MatchClausePlanner.cpp index fda817a224b..3bbc1985593 100644 --- a/src/graph/planner/match/MatchClausePlanner.cpp +++ b/src/graph/planner/match/MatchClausePlanner.cpp @@ -206,6 +206,12 @@ Status MatchClausePlanner::findStarts(std::vector& nodeInfos, matchClauseCtx->sentence->toString().c_str()); } + if (matchClausePlan.tail->isSingleInput()) { + auto start = StartNode::make(matchClauseCtx->qctx); + matchClausePlan.tail->setDep(0, start); + matchClausePlan.tail = start; + } + return Status::OK(); } diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 0be4d4c0f58..efbfd6a5f82 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -312,7 +312,10 @@ Status Validator::appendPlan(PlanNode* root) { return appendPlan(tail_, root); } -void Validator::rmLeftTailStartNode() { +// remove the left tail node which is start plannode +void Validator::rmLeftTailStartNode(PlanNode* appendPlanRoot) { + if (appendPlanRoot->kind() != PlanNode::Kind::kSwitchSpace) return; + if (tail_->kind() != PlanNode::Kind::kStart) return; PlanNode* node = root_; if (node->dependencies().size() == 0UL) return; @@ -320,7 +323,8 @@ void Validator::rmLeftTailStartNode() { node = const_cast(node->dependencies()[0]); } if (node->dependencies().size() == 1UL) { - node->dependencies().clear(); + node->dependencies().pop_back(); + tail_ = node; } } diff --git a/src/graph/validator/Validator.h b/src/graph/validator/Validator.h index 514b31deb7a..3a0078ae1c1 100644 --- a/src/graph/validator/Validator.h +++ b/src/graph/validator/Validator.h @@ -113,7 +113,7 @@ class Validator { } // remove the left tail node from the plan - void rmLeftTailStartNode(); + void rmLeftTailStartNode(PlanNode* appendPlanRoot); protected: Validator(Sentence* sentence, QueryContext* qctx); diff --git a/tests/tck/features/match/MultiLineMultiQueryParts.feature b/tests/tck/features/match/MultiLineMultiQueryParts.feature new file mode 100644 index 00000000000..4408d41b9e4 --- /dev/null +++ b/tests/tck/features/match/MultiLineMultiQueryParts.feature @@ -0,0 +1,272 @@ +# Copyright (c) 2021 vesoft inc. All rights reserved. +# +# This source code is licensed under Apache 2.0 License. +Feature: Multi Line Multi Query Parts + + Background: + Given a graph with space named "nba" + + Scenario: Multi Line Multi Path Patterns + When executing query: + """ + USE nba; + MATCH (m)-[]-(n), (n)-[]-(l) WHERE id(m)=="Tim Duncan" + RETURN m.player.name AS n1, n.player.name AS n2, + CASE WHEN l.team.name is not null THEN l.team.name + WHEN l.player.name is not null THEN l.player.name ELSE "null" END AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | + | "Tim Duncan" | "Aron Baynes" | "Tim Duncan" | + | "Tim Duncan" | "Boris Diaw" | "Hawks" | + | "Tim Duncan" | "Boris Diaw" | "Hornets" | + | "Tim Duncan" | "Boris Diaw" | "Jazz" | + | "Tim Duncan" | "Boris Diaw" | "Spurs" | + | "Tim Duncan" | "Boris Diaw" | "Suns" | + | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | + When executing query: + """ + USE nba; + MATCH (m)-[]-(n), (l)-[]-(n) WHERE id(m)=="Tim Duncan" + RETURN m.player.name AS n1, n.player.name AS n2, + CASE WHEN l.team.name is not null THEN l.team.name + WHEN l.player.name is not null THEN l.player.name ELSE "null" END AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | + | "Tim Duncan" | "Aron Baynes" | "Tim Duncan" | + | "Tim Duncan" | "Boris Diaw" | "Hawks" | + | "Tim Duncan" | "Boris Diaw" | "Hornets" | + | "Tim Duncan" | "Boris Diaw" | "Jazz" | + | "Tim Duncan" | "Boris Diaw" | "Spurs" | + | "Tim Duncan" | "Boris Diaw" | "Suns" | + | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | + When executing query: + """ + USE nba; + MATCH (m)-[]-(n), (n)-[]-(l) WHERE id(n)=="Tim Duncan" + RETURN m.player.name AS n1, n.player.name AS n2, l.player.name AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | + | "Aron Baynes" | "Tim Duncan" | "Aron Baynes" | + | "Aron Baynes" | "Tim Duncan" | "Boris Diaw" | + | "Aron Baynes" | "Tim Duncan" | "Danny Green" | + | "Aron Baynes" | "Tim Duncan" | "Danny Green" | + | "Aron Baynes" | "Tim Duncan" | "Dejounte Murray" | + | "Aron Baynes" | "Tim Duncan" | "LaMarcus Aldridge" | + | "Aron Baynes" | "Tim Duncan" | "LaMarcus Aldridge" | + | "Aron Baynes" | "Tim Duncan" | "Manu Ginobili" | + | "Aron Baynes" | "Tim Duncan" | "Manu Ginobili" | + | "Aron Baynes" | "Tim Duncan" | "Manu Ginobili" | + When executing query: + """ + USE nba; + MATCH (m)-[]-(n), (n)-[]-(l), (l)-[]-(h) WHERE id(m)=="Tim Duncan" + RETURN m.player.name AS n1, n.player.name AS n2, l.team.name AS n3, h.player.name AS n4 + ORDER BY n1, n2, n3, n4 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | n4 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Kyrie Irving" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Rajon Rondo" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Ray Allen" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Shaquile O'Neal" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Blake Griffin" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Grant Hill" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Boris Diaw" | + # Below scenario is not suppoted for the execution plan has a scan. + When executing query: + """ + USE nba; + MATCH (m)-[]-(n), (a)-[]-(c) WHERE id(m)=="Tim Duncan" + RETURN m,n,a,c + """ + Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. + + Scenario: Multi Line Multi Match + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + MATCH (n)-[]-(l) + RETURN m.player.name AS n1, n.player.name AS n2, + CASE WHEN l.player.name is not null THEN l.player.name + WHEN l.team.name is not null THEN l.team.name ELSE "null" END AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | + | "Tim Duncan" | "Aron Baynes" | "Tim Duncan" | + | "Tim Duncan" | "Boris Diaw" | "Hawks" | + | "Tim Duncan" | "Boris Diaw" | "Hornets" | + | "Tim Duncan" | "Boris Diaw" | "Jazz" | + | "Tim Duncan" | "Boris Diaw" | "Spurs" | + | "Tim Duncan" | "Boris Diaw" | "Suns" | + | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + MATCH (n)-[]-(l), (l)-[]-(h) + RETURN m.player.name AS n1, n.player.name AS n2, l.team.name AS n3, h.player.name AS n4 + ORDER BY n1, n2, n3, n4 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | n4 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Kyrie Irving" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Rajon Rondo" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Ray Allen" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Shaquile O'Neal" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Blake Griffin" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Grant Hill" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Boris Diaw" | + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + MATCH (n)-[]-(l) + MATCH (l)-[]-(h) + RETURN m.player.name AS n1, n.player.name AS n2, l.team.name AS n3, h.player.name AS n4 + ORDER BY n1, n2, n3, n4 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | n4 | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Kyrie Irving" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Rajon Rondo" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Ray Allen" | + | "Tim Duncan" | "Aron Baynes" | "Celtics" | "Shaquile O'Neal" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Blake Griffin" | + | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Grant Hill" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Aron Baynes" | + | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Boris Diaw" | + When executing query: + """ + USE nba; + MATCH (v:player{name:"Tony Parker"}) + WITH v AS a + MATCH p=(o:player{name:"Tim Duncan"})-[]->(a) + RETURN o.player.name + """ + Then the result should be, in order: + | o.player.name | + | "Tim Duncan" | + | "Tim Duncan" | + + Scenario: Multi Line Optional Match + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + OPTIONAL MATCH (n)<-[:serve]-(l) + RETURN m.player.name AS n1, n.player.name AS n2, l AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | n3 | + | "Tim Duncan" | "Aron Baynes" | NULL | + | "Tim Duncan" | "Boris Diaw" | NULL | + | "Tim Duncan" | "Danny Green" | NULL | + | "Tim Duncan" | "Danny Green" | NULL | + | "Tim Duncan" | "Dejounte Murray" | NULL | + | "Tim Duncan" | "LaMarcus Aldridge" | NULL | + | "Tim Duncan" | "LaMarcus Aldridge" | NULL | + | "Tim Duncan" | "Manu Ginobili" | NULL | + | "Tim Duncan" | "Manu Ginobili" | NULL | + | "Tim Duncan" | "Manu Ginobili" | NULL | + # Below scenario is not suppoted for the execution plan has a scan. + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + OPTIONAL MATCH (a)<-[]-(b) + RETURN m.player.name AS n1, n.player.name AS n2, a.player.name AS n3 ORDER BY n1, n2, n3 LIMIT 10 + """ + Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. + + Scenario: Multi Line Multi Query Parts + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + WITH n, n.player.name AS n1 ORDER BY n1 LIMIT 10 + MATCH (n)-[]-(l) + RETURN n.player.name AS n1, + CASE WHEN l.player.name is not null THEN l.player.name + WHEN l.team.name is not null THEN l.team.name ELSE "null" END AS n2 ORDER BY n1, n2 LIMIT 10 + """ + Then the result should be, in order: + | n1 | n2 | + | "Aron Baynes" | "Celtics" | + | "Aron Baynes" | "Pistons" | + | "Aron Baynes" | "Spurs" | + | "Aron Baynes" | "Tim Duncan" | + | "Boris Diaw" | "Hawks" | + | "Boris Diaw" | "Hornets" | + | "Boris Diaw" | "Jazz" | + | "Boris Diaw" | "Spurs" | + | "Boris Diaw" | "Suns" | + | "Boris Diaw" | "Tim Duncan" | + When executing query: + """ + USE nba; + MATCH (m:player{name:"Tim Duncan"})-[:like]-(n)--() + WITH m,count(*) AS lcount + MATCH (m)--(n) + RETURN count(*) AS scount, lcount + """ + Then the result should be, in order: + | scount | lcount | + | 19 | 110 | + When executing query: + """ + USE nba; + MATCH (m:player{name:"Tim Duncan"})-[:like]-(n)--() + WITH m,n + MATCH (m)--(n) + RETURN count(*) AS scount + """ + Then the result should be, in order: + | scount | + | 270 | + # Below scenario is not suppoted for the execution plan has a scan. + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + WITH n, n.player.name AS n1 ORDER BY n1 LIMIT 10 + MATCH (a)-[]-(b) + RETURN a.player.name AS n1, b.player.name AS n2 ORDER BY n1, n2 LIMIT 10 + """ + Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. + + Scenario: Multi Line Some Erros + When executing query: + """ + USE nba; + MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" + WITH n, n.player.name AS n1 ORDER BY n1 LIMIT 10 + RETURN m + """ + Then a SemanticError should be raised at runtime: Alias used but not defined: `m' + When executing query: + """ + USE nba; + MATCH (v:player)-[e]-(v:team) RETURN v, e + """ + Then a SemanticError should be raised at runtime: `v': Redefined alias in a single path pattern. From cb6897059631f38d8953ae8c7ef254646e52a5b0 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:02:07 +0800 Subject: [PATCH 08/13] fix --- src/graph/planner/SequentialPlanner.cpp | 1 + src/graph/validator/Validator.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index 9e0690f1e3f..eb42db530de 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -24,6 +24,7 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { subPlan.root = validators.back()->root(); ifBuildDataCollect(subPlan, qctx); for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) { + (iter + 1)->get()->rmLeftTailStartNode(iter->get()->root()); NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index efbfd6a5f82..c5d7dfb3e16 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -300,7 +300,7 @@ Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { DCHECK(node != nullptr); DCHECK(appended != nullptr); - if (!node->isSingleInput()) { + if (appended->kind() != PlanNode::Kind::kSwitchSpace && !node->isSingleInput()) { return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } @@ -323,7 +323,8 @@ void Validator::rmLeftTailStartNode(PlanNode* appendPlanRoot) { node = const_cast(node->dependencies()[0]); } if (node->dependencies().size() == 1UL) { - node->dependencies().pop_back(); + // remain one size for add dependency + node->dependencies()[0] = nullptr; tail_ = node; } } From 894ce29279f3615b87b87cc048a9f5328526e6a4 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:49:01 +0800 Subject: [PATCH 09/13] enhance annotation --- src/graph/planner/SequentialPlanner.cpp | 5 ++++- src/graph/validator/Validator.cpp | 17 ++++++++++------- src/graph/validator/Validator.h | 3 +-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index eb42db530de..912297b91c8 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -24,7 +24,10 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { subPlan.root = validators.back()->root(); ifBuildDataCollect(subPlan, qctx); for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) { - (iter + 1)->get()->rmLeftTailStartNode(iter->get()->root()); + // Remove left tail kStart plannode before append plan. + // It allows that kUse sentence append kMatch Sentence. + // For example: Use ...; Match ... + (iter + 1)->get()->rmLeftTailStartNode(iter->get()->sentence()->kind()); NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index c5d7dfb3e16..d8cc5597e8e 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -312,18 +312,21 @@ Status Validator::appendPlan(PlanNode* root) { return appendPlan(tail_, root); } -// remove the left tail node which is start plannode -void Validator::rmLeftTailStartNode(PlanNode* appendPlanRoot) { - if (appendPlanRoot->kind() != PlanNode::Kind::kSwitchSpace) return; - if (tail_->kind() != PlanNode::Kind::kStart) return; - PlanNode* node = root_; - if (node->dependencies().size() == 0UL) return; +// When appending plans, it need to remove left tail plannode. +// Because the left tail plannode is StartNode that need to remove it, +// and remain one size for add dependency +void Validator::rmLeftTailStartNode(Sentence::Kind appendPlanKind) { + if (appendPlanKind != Sentence::Kind::kUse || sentence_->kind() == Sentence::Kind::kMatch || + tail_->kind() != PlanNode::Kind::kStart || root_->dependencies().size() == 0UL) { + return; + } + PlanNode* node = root_; while (node->dependencies()[0]->dependencies().size() > 0UL) { node = const_cast(node->dependencies()[0]); } if (node->dependencies().size() == 1UL) { - // remain one size for add dependency + // Remain one size for add dependency node->dependencies()[0] = nullptr; tail_ = node; } diff --git a/src/graph/validator/Validator.h b/src/graph/validator/Validator.h index 3a0078ae1c1..408c09bd561 100644 --- a/src/graph/validator/Validator.h +++ b/src/graph/validator/Validator.h @@ -112,8 +112,7 @@ class Validator { return sentence_; } - // remove the left tail node from the plan - void rmLeftTailStartNode(PlanNode* appendPlanRoot); + void rmLeftTailStartNode(Sentence::Kind appendPlanKind); protected: Validator(Sentence* sentence, QueryContext* qctx); From 4d1ecbe9171dc8bfe37df63d4b11ddcd7dc4b852 Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:14:24 +0800 Subject: [PATCH 10/13] fix review --- src/graph/planner/SequentialPlanner.cpp | 26 ++++++++++++++++++++- src/graph/planner/SequentialPlanner.h | 2 ++ src/graph/validator/SequentialValidator.cpp | 1 + src/graph/validator/Validator.cpp | 23 ++---------------- src/graph/validator/Validator.h | 2 -- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index 912297b91c8..30bd6ac93fc 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -27,7 +27,8 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { // Remove left tail kStart plannode before append plan. // It allows that kUse sentence append kMatch Sentence. // For example: Use ...; Match ... - (iter + 1)->get()->rmLeftTailStartNode(iter->get()->sentence()->kind()); + rmLeftTailStartNode( + (iter + 1)->get()->root(), (iter + 1)->get()->tail(), iter->get()->sentence()->kind()); NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { @@ -63,5 +64,28 @@ void SequentialPlanner::ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx) break; } } + +// When appending plans, it need to remove left tail plannode. +// Because the left tail plannode is StartNode that need to remove it, +// and remain one size for add dependency +// TODO: It's a temporary solution, remove it after Execute multiple sequences one by one. +void SequentialPlanner::rmLeftTailStartNode(PlanNode* root, + PlanNode* tail, + Sentence::Kind appendPlanKind) { + if (appendPlanKind != Sentence::Kind::kUse || tail->kind() != PlanNode::Kind::kStart || + root->dependencies().size() == 0UL) { + return; + } + + PlanNode* node = root; + while (node->dependencies()[0]->dependencies().size() > 0UL) { + node = const_cast(node->dependencies()[0]); + } + if (node->dependencies().size() == 1UL) { + // Remain one size for add dependency + node->dependencies()[0] = nullptr; + tail = node; + } +} } // namespace graph } // namespace nebula diff --git a/src/graph/planner/SequentialPlanner.h b/src/graph/planner/SequentialPlanner.h index 656bede413e..09b21b1536b 100644 --- a/src/graph/planner/SequentialPlanner.h +++ b/src/graph/planner/SequentialPlanner.h @@ -27,6 +27,8 @@ class SequentialPlanner final : public Planner { void ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx); + void rmLeftTailStartNode(PlanNode* root, PlanNode* tail, Sentence::Kind appendPlanKind); + private: SequentialPlanner() = default; }; diff --git a/src/graph/validator/SequentialValidator.cpp b/src/graph/validator/SequentialValidator.cpp index 6ec59785523..f7ffe9d440c 100644 --- a/src/graph/validator/SequentialValidator.cpp +++ b/src/graph/validator/SequentialValidator.cpp @@ -48,5 +48,6 @@ const Sentence* SequentialValidator::getFirstSentence(const Sentence* sentence) auto pipe = static_cast(sentence); return getFirstSentence(pipe->left()); } + } // namespace graph } // namespace nebula diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index d8cc5597e8e..03f8d48867d 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -8,6 +8,7 @@ #include #include "common/function/FunctionManager.h" +#include "graph/planner/plan/PlanNode.h" #include "graph/planner/plan/Query.h" #include "graph/util/ExpressionUtils.h" #include "graph/util/SchemaUtil.h" @@ -300,7 +301,7 @@ Status Validator::appendPlan(PlanNode* node, PlanNode* appended) { DCHECK(node != nullptr); DCHECK(appended != nullptr); - if (appended->kind() != PlanNode::Kind::kSwitchSpace && !node->isSingleInput()) { + if (!node->isSingleInput()) { return Status::SemanticError("PlanNode(%s) not support to append an input.", PlanNode::toString(node->kind())); } @@ -312,26 +313,6 @@ Status Validator::appendPlan(PlanNode* root) { return appendPlan(tail_, root); } -// When appending plans, it need to remove left tail plannode. -// Because the left tail plannode is StartNode that need to remove it, -// and remain one size for add dependency -void Validator::rmLeftTailStartNode(Sentence::Kind appendPlanKind) { - if (appendPlanKind != Sentence::Kind::kUse || sentence_->kind() == Sentence::Kind::kMatch || - tail_->kind() != PlanNode::Kind::kStart || root_->dependencies().size() == 0UL) { - return; - } - - PlanNode* node = root_; - while (node->dependencies()[0]->dependencies().size() > 0UL) { - node = const_cast(node->dependencies()[0]); - } - if (node->dependencies().size() == 1UL) { - // Remain one size for add dependency - node->dependencies()[0] = nullptr; - tail_ = node; - } -} - Status Validator::validate() { if (!vctx_) { VLOG(1) << "Validate context was not given."; diff --git a/src/graph/validator/Validator.h b/src/graph/validator/Validator.h index 408c09bd561..b1206769fc8 100644 --- a/src/graph/validator/Validator.h +++ b/src/graph/validator/Validator.h @@ -112,8 +112,6 @@ class Validator { return sentence_; } - void rmLeftTailStartNode(Sentence::Kind appendPlanKind); - protected: Validator(Sentence* sentence, QueryContext* qctx); From 7be7d4a39e1d4f48d8d1d059e9629a3fe06f6d7c Mon Sep 17 00:00:00 2001 From: jackwener <30525741+jackwener@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:38:11 +0800 Subject: [PATCH 11/13] fix --- src/graph/planner/SequentialPlanner.cpp | 16 +++++++--------- src/graph/planner/SequentialPlanner.h | 3 ++- src/graph/validator/Validator.h | 4 ++++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index 30bd6ac93fc..9207d5e8056 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -27,8 +27,7 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { // Remove left tail kStart plannode before append plan. // It allows that kUse sentence append kMatch Sentence. // For example: Use ...; Match ... - rmLeftTailStartNode( - (iter + 1)->get()->root(), (iter + 1)->get()->tail(), iter->get()->sentence()->kind()); + rmLeftTailStartNode((iter + 1)->get(), iter->get()->sentence()->kind()); NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); } if (validators.front()->tail()->isSingleInput()) { @@ -69,22 +68,21 @@ void SequentialPlanner::ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx) // Because the left tail plannode is StartNode that need to remove it, // and remain one size for add dependency // TODO: It's a temporary solution, remove it after Execute multiple sequences one by one. -void SequentialPlanner::rmLeftTailStartNode(PlanNode* root, - PlanNode* tail, - Sentence::Kind appendPlanKind) { - if (appendPlanKind != Sentence::Kind::kUse || tail->kind() != PlanNode::Kind::kStart || - root->dependencies().size() == 0UL) { +void SequentialPlanner::rmLeftTailStartNode(Validator* validator, Sentence::Kind appendPlanKind) { + if (appendPlanKind != Sentence::Kind::kUse || + validator->tail()->kind() != PlanNode::Kind::kStart || + validator->root()->dependencies().size() == 0UL) { return; } - PlanNode* node = root; + PlanNode* node = validator->root(); while (node->dependencies()[0]->dependencies().size() > 0UL) { node = const_cast(node->dependencies()[0]); } if (node->dependencies().size() == 1UL) { // Remain one size for add dependency node->dependencies()[0] = nullptr; - tail = node; + validator->setTail(node); } } } // namespace graph diff --git a/src/graph/planner/SequentialPlanner.h b/src/graph/planner/SequentialPlanner.h index 09b21b1536b..a37efdf7e97 100644 --- a/src/graph/planner/SequentialPlanner.h +++ b/src/graph/planner/SequentialPlanner.h @@ -8,6 +8,7 @@ #include "graph/context/QueryContext.h" #include "graph/planner/Planner.h" +#include "graph/validator/Validator.h" namespace nebula { namespace graph { @@ -27,7 +28,7 @@ class SequentialPlanner final : public Planner { void ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx); - void rmLeftTailStartNode(PlanNode* root, PlanNode* tail, Sentence::Kind appendPlanKind); + void rmLeftTailStartNode(Validator* validator, Sentence::Kind appendPlanKind); private: SequentialPlanner() = default; diff --git a/src/graph/validator/Validator.h b/src/graph/validator/Validator.h index b1206769fc8..d7bbcb516de 100644 --- a/src/graph/validator/Validator.h +++ b/src/graph/validator/Validator.h @@ -87,6 +87,10 @@ class Validator { exprProps_ = exprProps; } + void setTail(PlanNode* tail) { + tail_ = tail; + } + const std::set& userDefinedVarNameList() const { return userDefinedVarNameList_; } From 1d1c55f925bdc5900b2950fc3a0fca6a0bad42a8 Mon Sep 17 00:00:00 2001 From: jackwener Date: Wed, 26 Jan 2022 21:39:22 +0800 Subject: [PATCH 12/13] fix review --- src/graph/planner/SequentialPlanner.cpp | 4 +-- .../match/MultiLineMultiQueryParts.feature | 27 ------------------- .../features/match/MultiQueryParts.feature | 6 ++--- 3 files changed, 5 insertions(+), 32 deletions(-) diff --git a/src/graph/planner/SequentialPlanner.cpp b/src/graph/planner/SequentialPlanner.cpp index 9207d5e8056..f7095d5fec6 100644 --- a/src/graph/planner/SequentialPlanner.cpp +++ b/src/graph/planner/SequentialPlanner.cpp @@ -25,7 +25,7 @@ StatusOr SequentialPlanner::transform(AstContext* astCtx) { ifBuildDataCollect(subPlan, qctx); for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) { // Remove left tail kStart plannode before append plan. - // It allows that kUse sentence append kMatch Sentence. + // It allows that kUse sentence to append kMatch Sentence. // For example: Use ...; Match ... rmLeftTailStartNode((iter + 1)->get(), iter->get()->sentence()->kind()); NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root())); @@ -65,7 +65,7 @@ void SequentialPlanner::ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx) } // When appending plans, it need to remove left tail plannode. -// Because the left tail plannode is StartNode that need to remove it, +// Because the left tail plannode is StartNode which needs to be removed, // and remain one size for add dependency // TODO: It's a temporary solution, remove it after Execute multiple sequences one by one. void SequentialPlanner::rmLeftTailStartNode(Validator* validator, Sentence::Kind appendPlanKind) { diff --git a/tests/tck/features/match/MultiLineMultiQueryParts.feature b/tests/tck/features/match/MultiLineMultiQueryParts.feature index 4408d41b9e4..bacd6370663 100644 --- a/tests/tck/features/match/MultiLineMultiQueryParts.feature +++ b/tests/tck/features/match/MultiLineMultiQueryParts.feature @@ -84,14 +84,6 @@ Feature: Multi Line Multi Query Parts | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Grant Hill" | | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Aron Baynes" | | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Boris Diaw" | - # Below scenario is not suppoted for the execution plan has a scan. - When executing query: - """ - USE nba; - MATCH (m)-[]-(n), (a)-[]-(c) WHERE id(m)=="Tim Duncan" - RETURN m,n,a,c - """ - Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. Scenario: Multi Line Multi Match When executing query: @@ -189,15 +181,6 @@ Feature: Multi Line Multi Query Parts | "Tim Duncan" | "Manu Ginobili" | NULL | | "Tim Duncan" | "Manu Ginobili" | NULL | | "Tim Duncan" | "Manu Ginobili" | NULL | - # Below scenario is not suppoted for the execution plan has a scan. - When executing query: - """ - USE nba; - MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" - OPTIONAL MATCH (a)<-[]-(b) - RETURN m.player.name AS n1, n.player.name AS n2, a.player.name AS n3 ORDER BY n1, n2, n3 LIMIT 10 - """ - Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. Scenario: Multi Line Multi Query Parts When executing query: @@ -244,16 +227,6 @@ Feature: Multi Line Multi Query Parts Then the result should be, in order: | scount | | 270 | - # Below scenario is not suppoted for the execution plan has a scan. - When executing query: - """ - USE nba; - MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" - WITH n, n.player.name AS n1 ORDER BY n1 LIMIT 10 - MATCH (a)-[]-(b) - RETURN a.player.name AS n1, b.player.name AS n2 ORDER BY n1, n2 LIMIT 10 - """ - Then a ExecutionError should be raised at runtime: Scan vertices or edges need to specify a limit number, or limit number can not push down. Scenario: Multi Line Some Erros When executing query: diff --git a/tests/tck/features/match/MultiQueryParts.feature b/tests/tck/features/match/MultiQueryParts.feature index 07cdc177de6..16dff147631 100644 --- a/tests/tck/features/match/MultiQueryParts.feature +++ b/tests/tck/features/match/MultiQueryParts.feature @@ -80,7 +80,7 @@ Feature: Multi Query Parts | "Tim Duncan" | "Aron Baynes" | "Pistons" | "Grant Hill" | | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Aron Baynes" | | "Tim Duncan" | "Aron Baynes" | "Spurs" | "Boris Diaw" | - # Below scenario is not suppoted for the execution plan has a scan. + # Below scenario is not supported for the execution plan has a scan. When executing query: """ MATCH (m)-[]-(n), (a)-[]-(c) WHERE id(m)=="Tim Duncan" @@ -179,7 +179,7 @@ Feature: Multi Query Parts | "Tim Duncan" | "Manu Ginobili" | NULL | | "Tim Duncan" | "Manu Ginobili" | NULL | | "Tim Duncan" | "Manu Ginobili" | NULL | - # Below scenario is not suppoted for the execution plan has a scan. + # Below scenario is not supported for the execution plan has a scan. When executing query: """ MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" @@ -230,7 +230,7 @@ Feature: Multi Query Parts Then the result should be, in order: | scount | | 270 | - # Below scenario is not suppoted for the execution plan has a scan. + # Below scenario is not supported for the execution plan has a scan. When executing query: """ MATCH (m)-[]-(n) WHERE id(m)=="Tim Duncan" From 91f1ec27d5f42bb599780cff9ea125b518014552 Mon Sep 17 00:00:00 2001 From: jackwener Date: Wed, 26 Jan 2022 22:09:15 +0800 Subject: [PATCH 13/13] remove redundant --- .../match/MultiLineMultiQueryParts.feature | 20 ------------------- .../features/match/MultiQueryParts.feature | 19 ------------------ 2 files changed, 39 deletions(-) diff --git a/tests/tck/features/match/MultiLineMultiQueryParts.feature b/tests/tck/features/match/MultiLineMultiQueryParts.feature index bacd6370663..63aaf7e4899 100644 --- a/tests/tck/features/match/MultiLineMultiQueryParts.feature +++ b/tests/tck/features/match/MultiLineMultiQueryParts.feature @@ -27,26 +27,6 @@ Feature: Multi Line Multi Query Parts | "Tim Duncan" | "Boris Diaw" | "Spurs" | | "Tim Duncan" | "Boris Diaw" | "Suns" | | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | - When executing query: - """ - USE nba; - MATCH (m)-[]-(n), (l)-[]-(n) WHERE id(m)=="Tim Duncan" - RETURN m.player.name AS n1, n.player.name AS n2, - CASE WHEN l.team.name is not null THEN l.team.name - WHEN l.player.name is not null THEN l.player.name ELSE "null" END AS n3 ORDER BY n1, n2, n3 LIMIT 10 - """ - Then the result should be, in order: - | n1 | n2 | n3 | - | "Tim Duncan" | "Aron Baynes" | "Celtics" | - | "Tim Duncan" | "Aron Baynes" | "Pistons" | - | "Tim Duncan" | "Aron Baynes" | "Spurs" | - | "Tim Duncan" | "Aron Baynes" | "Tim Duncan" | - | "Tim Duncan" | "Boris Diaw" | "Hawks" | - | "Tim Duncan" | "Boris Diaw" | "Hornets" | - | "Tim Duncan" | "Boris Diaw" | "Jazz" | - | "Tim Duncan" | "Boris Diaw" | "Spurs" | - | "Tim Duncan" | "Boris Diaw" | "Suns" | - | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | When executing query: """ USE nba; diff --git a/tests/tck/features/match/MultiQueryParts.feature b/tests/tck/features/match/MultiQueryParts.feature index 16dff147631..2a5cda28864 100644 --- a/tests/tck/features/match/MultiQueryParts.feature +++ b/tests/tck/features/match/MultiQueryParts.feature @@ -26,25 +26,6 @@ Feature: Multi Query Parts | "Tim Duncan" | "Boris Diaw" | "Spurs" | | "Tim Duncan" | "Boris Diaw" | "Suns" | | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | - When executing query: - """ - MATCH (m)-[]-(n), (l)-[]-(n) WHERE id(m)=="Tim Duncan" - RETURN m.player.name AS n1, n.player.name AS n2, - CASE WHEN l.team.name is not null THEN l.team.name - WHEN l.player.name is not null THEN l.player.name ELSE "null" END AS n3 ORDER BY n1, n2, n3 LIMIT 10 - """ - Then the result should be, in order: - | n1 | n2 | n3 | - | "Tim Duncan" | "Aron Baynes" | "Celtics" | - | "Tim Duncan" | "Aron Baynes" | "Pistons" | - | "Tim Duncan" | "Aron Baynes" | "Spurs" | - | "Tim Duncan" | "Aron Baynes" | "Tim Duncan" | - | "Tim Duncan" | "Boris Diaw" | "Hawks" | - | "Tim Duncan" | "Boris Diaw" | "Hornets" | - | "Tim Duncan" | "Boris Diaw" | "Jazz" | - | "Tim Duncan" | "Boris Diaw" | "Spurs" | - | "Tim Duncan" | "Boris Diaw" | "Suns" | - | "Tim Duncan" | "Boris Diaw" | "Tim Duncan" | When executing query: """ MATCH (m)-[]-(n), (n)-[]-(l) WHERE id(n)=="Tim Duncan"