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
26 changes: 26 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 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()));
}
if (validators.front()->tail()->isSingleInput()) {
Expand Down Expand Up @@ -59,5 +63,27 @@ 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 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) {
if (appendPlanKind != Sentence::Kind::kUse ||
validator->tail()->kind() != PlanNode::Kind::kStart ||
validator->root()->dependencies().size() == 0UL) {
return;
}

PlanNode* node = validator->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;
validator->setTail(node);
}
}
} // namespace graph
} // namespace nebula
3 changes: 3 additions & 0 deletions src/graph/planner/SequentialPlanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "graph/context/QueryContext.h"
#include "graph/planner/Planner.h"
#include "graph/validator/Validator.h"

namespace nebula {
namespace graph {
Expand All @@ -27,6 +28,8 @@ class SequentialPlanner final : public Planner {

void ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx);

void rmLeftTailStartNode(Validator* validator, Sentence::Kind appendPlanKind);

private:
SequentialPlanner() = default;
};
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
1 change: 1 addition & 0 deletions src/graph/validator/SequentialValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ const Sentence* SequentialValidator::getFirstSentence(const Sentence* sentence)
auto pipe = static_cast<const PipedSentence*>(sentence);
return getFirstSentence(pipe->left());
}

} // namespace graph
} // namespace nebula
4 changes: 3 additions & 1 deletion src/graph/validator/Validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <thrift/lib/cpp/util/EnumUtils.h>

#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"
Expand Down Expand Up @@ -299,8 +300,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.",
return Status::SemanticError("PlanNode(%s) not support to append an input.",
PlanNode::toString(node->kind()));
}
static_cast<SingleDependencyNode*>(node)->dependsOn(appended);
Expand Down
4 changes: 4 additions & 0 deletions src/graph/validator/Validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ class Validator {
exprProps_ = exprProps;
}

void setTail(PlanNode* tail) {
jackwener marked this conversation as resolved.
Show resolved Hide resolved
tail_ = tail;
}

const std::set<std::string>& userDefinedVarNameList() const {
return userDefinedVarNameList_;
}
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"}) |
225 changes: 225 additions & 0 deletions tests/tck/features/match/MultiLineMultiQueryParts.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# 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), (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" |

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 |

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 |

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

25 changes: 3 additions & 22 deletions tests/tck/features/match/MultiQueryParts.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why delete this?

"""
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"
Expand Down Expand Up @@ -80,7 +61,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"
Expand Down Expand Up @@ -179,7 +160,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"
Expand Down Expand Up @@ -230,7 +211,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"
Expand Down