Skip to content

Commit

Permalink
support find circular (#5636)
Browse files Browse the repository at this point in the history
Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com>
  • Loading branch information
nevermore3 and Sophie-Xie committed Jul 13, 2023
1 parent 9474b95 commit 5ffd73e
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/graph/executor/algo/ShortestPathExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ size_t ShortestPathExecutor::checkInput(HashSet& startVids, HashSet& endVids) {
auto iter = ectx_->getResult(pathNode_->inputVar()).iter();
const auto& metaVidType = *(qctx()->rctx()->session()->space().spaceDesc.vid_type_ref());
auto vidType = SchemaUtil::propTypeToValueType(metaVidType.get_type());
bool isZeroStep = pathNode_->stepRange().min() == 0;
for (; iter->valid(); iter->next()) {
auto start = iter->getColumn(0);
auto end = iter->getColumn(1);
Expand All @@ -52,8 +53,10 @@ size_t ShortestPathExecutor::checkInput(HashSet& startVids, HashSet& endVids) {
<< ", end type: " << end.type() << ", space vid type: " << vidType;
continue;
}
if (start == end) {
// continue or return error

// When the minimum number of steps is 0, and the starting node and the destination node
// are the same. the shortest path between the two nodes is 0
if (isZeroStep && start == end) {
continue;
}
startVids.emplace(std::move(start));
Expand Down
4 changes: 4 additions & 0 deletions src/graph/planner/match/ShortestPathPlanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ StatusOr<SubPlan> ShortestPathPlanner::transform(WhereClauseContext* bindWhereCl
SubPlan subplan;
bool singleShortest = path_.pathType == Path::PathType::kSingleShortest;
auto& nodeInfos = path_.nodeInfos;
if (nodeInfos.front().alias == nodeInfos.back().alias) {
return Status::SemanticError(
"The shortest path algorithm does not work when the start and end nodes are the same");
}
auto& edge = path_.edgeInfos.front();
std::vector<std::string> colNames;
colNames.emplace_back(nodeInfos.front().alias);
Expand Down
70 changes: 70 additions & 0 deletions tests/tck/features/match/AllShortestPaths.feature
Original file line number Diff line number Diff line change
Expand Up @@ -898,3 +898,73 @@ Feature: allShortestPaths
| 11 | Argument | | |
| 14 | Project | 13 | |
| 13 | Argument | | |

Scenario: allShortestPaths for same start and end node
When executing query:
"""
MATCH (a:player{name:'Yao Ming'})
MATCH p = allShortestPaths((a)-[:like*1..3]-(a))
RETURN p
"""
Then a SemanticError should be raised at runtime: The shortest path algorithm does not work when the start and end nodes are the same
When executing query:
"""
MATCH p = allShortestPaths((a:player{name:'Yao Ming'})-[:like*1..3]-(a))
RETURN p
"""
Then a SemanticError should be raised at runtime: The shortest path algorithm does not work when the start and end nodes are the same
When executing query:
"""
MATCH (a:player{name:'Yao Ming'}), (b:player{name:'Yao Ming'})
MATCH p = allShortestPaths((a)-[:like*0..3]-(b))
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
When executing query:
"""
MATCH p = allShortestPaths((a)-[:like*0..3]-(b))
WHERE id(a) == 'Yao Ming' AND id(b) == 'Yao Ming'
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
When executing query:
"""
MATCH (a:player{name:'Yao Ming'}), (b:player{name:'Yao Ming'})
MATCH p = allShortestPaths((a)-[:like*1..3]-(b))
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Shaquille O'Neal" :player{age: 47, name: "Shaquille O'Neal"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
When executing query:
"""
MATCH (a:player{name:'Yao Ming'})
MATCH p = allShortestPaths((a)-[:like*1..3]-(b:player{name:'Yao Ming'}))
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Shaquille O'Neal" :player{age: 47, name: "Shaquille O'Neal"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
When executing query:
"""
MATCH p = allShortestPaths((a:player{name:'Yao Ming'})-[:like*1..3]-(b:player{name:'Yao Ming'}))
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Shaquille O'Neal" :player{age: 47, name: "Shaquille O'Neal"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
When executing query:
"""
MATCH p = allShortestPaths((a)-[:like*1..3]-(b))
WHERE id(a) == 'Yao Ming' AND id(b) == 'Yao Ming'
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
| <("Yao Ming" :player{age: 38, name: "Yao Ming"})-[:like@0 {likeness: 90}]->("Shaquille O'Neal" :player{age: 47, name: "Shaquille O'Neal"})<-[:like@0 {likeness: 90}]-("Yao Ming" :player{age: 38, name: "Yao Ming"})> |
66 changes: 66 additions & 0 deletions tests/tck/features/match/SingleShorestPath.feature
Original file line number Diff line number Diff line change
Expand Up @@ -746,3 +746,69 @@ Feature: single shortestPath
| <("JaVale McGee":player{age:31,name:"JaVale McGee"})-[:serve@0{end_year:2018,start_year:2016}]->("Warriors":team{name:"Warriors"})<-[:serve@0{end_year:2009,start_year:2007}]-("Marco Belinelli":player{age:32,name:"Marco Belinelli"})-[:like@0{likeness:50}]->("Tony Parker":player{age:36,name:"Tony Parker"})> |
| <("LeBron James":player{age:34,name:"LeBron James"})<-[:like@0{likeness:99}]-("Dejounte Murray":player{age:29,name:"Dejounte Murray"})-[:like@0{likeness:99}]->("Tony Parker":player{age:36,name:"Tony Parker"})> |
| <("Kings":team{name:"Kings"})<-[:serve@0{end_year:2016,start_year:2015}]-("Marco Belinelli":player{age:32,name:"Marco Belinelli"})-[:like@0{likeness:50}]->("Tony Parker":player{age:36,name:"Tony Parker"})> |

Scenario: shortestPath for same start and end node
When executing query:
"""
MATCH (a:player{name:'Yao Ming'})
MATCH p = shortestPath((a)-[:like*1..3]-(a))
RETURN p
"""
Then a SemanticError should be raised at runtime: The shortest path algorithm does not work when the start and end nodes are the same
When executing query:
"""
MATCH p = shortestPath((a:player{name:'Yao Ming'})-[:like*1..3]-(a))
RETURN p
"""
Then a SemanticError should be raised at runtime: The shortest path algorithm does not work when the start and end nodes are the same
When executing query:
"""
MATCH (a:player{name:'Yao Ming'}), (b:player{name:'Yao Ming'})
MATCH p = shortestPath((a)-[:like*0..3]-(b))
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
When executing query:
"""
MATCH p = shortestPath((a)-[:like*0..3]-(b))
WHERE id(a) == 'Yao Ming' AND id(b) == 'Yao Ming'
RETURN p
"""
Then the result should be, in any order, with relax comparison:
| p |
When executing query:
"""
MATCH (a:player{name:'Yao Ming'}), (b:player{name:'Yao Ming'})
MATCH p = shortestPath((a)-[:like*1..3]-(b))
RETURN a, b
"""
Then the result should be, in any order, with relax comparison:
| a | b |
| ("Yao Ming" :player{age: 38, name: "Yao Ming"}) | ("Yao Ming" :player{age: 38, name: "Yao Ming"}) |
When executing query:
"""
MATCH (a:player{name:'Yao Ming'})
MATCH p = shortestPath((a)-[:like*1..3]-(b:player{name:'Yao Ming'}))
RETURN a,b
"""
Then the result should be, in any order, with relax comparison:
| a | b |
| ("Yao Ming" :player{age: 38, name: "Yao Ming"}) | ("Yao Ming" :player{age: 38, name: "Yao Ming"}) |
When executing query:
"""
MATCH p = shortestPath((a:player{name:'Yao Ming'})-[:like*1..3]-(b:player{name:'Yao Ming'}))
RETURN a,b
"""
Then the result should be, in any order, with relax comparison:
| a | b |
| ("Yao Ming" :player{age: 38, name: "Yao Ming"}) | ("Yao Ming" :player{age: 38, name: "Yao Ming"}) |
When executing query:
"""
MATCH p = shortestPath((a)-[:like*1..3]-(b))
WHERE id(a) == 'Yao Ming' AND id(b) == 'Yao Ming'
RETURN a,b
"""
Then the result should be, in any order, with relax comparison:
| a | b |
| ("Yao Ming" :player{age: 38, name: "Yao Ming"}) | ("Yao Ming" :player{age: 38, name: "Yao Ming"}) |

0 comments on commit 5ffd73e

Please sign in to comment.