Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Match cannot be followed by use space #3748

Merged
merged 17 commits into from
Jan 27, 2022
4 changes: 4 additions & 0 deletions src/graph/planner/SequentialPlanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ StatusOr<SubPlan> SequentialPlanner::transform(AstContext* astCtx) {
subPlan.root = validators.back()->root();
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.
jackwener marked this conversation as resolved.
Show resolved Hide resolved
// 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()) {
Expand Down
4 changes: 4 additions & 0 deletions src/graph/planner/plan/PlanNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 23 additions & 2 deletions src/graph/validator/Validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,9 @@ std::vector<std::string> 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.",

if (appended->kind() != PlanNode::Kind::kSwitchSpace && !node->isSingleInput()) {
return Status::SemanticError("PlanNode(%s) not support to append an input.",
PlanNode::toString(node->kind()));
}
static_cast<SingleDependencyNode*>(node)->dependsOn(appended);
Expand All @@ -311,6 +312,26 @@ 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<PlanNode*>(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.";
Expand Down
2 changes: 2 additions & 0 deletions src/graph/validator/Validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ class Validator {
return sentence_;
}

void rmLeftTailStartNode(Sentence::Kind appendPlanKind);

protected:
Validator(Sentence* sentence, QueryContext* qctx);

Expand Down
10 changes: 10 additions & 0 deletions tests/tck/features/match/Base.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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"}) |
272 changes: 272 additions & 0 deletions tests/tck/features/match/MultiLineMultiQueryParts.feature
Original file line number Diff line number Diff line change
@@ -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" |
jackwener marked this conversation as resolved.
Show resolved Hide resolved
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.
jackwener marked this conversation as resolved.
Show resolved Hide resolved
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.
jackwener marked this conversation as resolved.
Show resolved Hide resolved
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test case like yield 1; match ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for USE space

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test the error