From a0c9b1c2483f53a2ef508a71ee8b36b8b01c095a Mon Sep 17 00:00:00 2001 From: jievince <38901892+jievince@users.noreply.github.com> Date: Mon, 26 Dec 2022 16:11:31 +0800 Subject: [PATCH] add more cases --- src/graph/context/Symbols.cpp | 4 + src/graph/context/Symbols.h | 2 + src/graph/validator/AssignmentValidator.cpp | 3 + tests/tck/features/aggregate/Agg.feature | 65 +++++++++ tests/tck/features/go/GroupbyLimit.feature | 20 +++ tests/tck/features/go/Orderby.feature | 20 +++ .../features/match/PipeAndVariable.feature | 133 +++++++++++++++++- tests/tck/features/set/Set.feature | 92 ++++++++++++ 8 files changed, 338 insertions(+), 1 deletion(-) diff --git a/src/graph/context/Symbols.cpp b/src/graph/context/Symbols.cpp index 83a493715b2..8e2c1b60969 100644 --- a/src/graph/context/Symbols.cpp +++ b/src/graph/context/Symbols.cpp @@ -34,6 +34,10 @@ std::string SymbolTable::toString() const { return ss.str(); } +bool SymbolTable::existsVar(const std::string& varName) const { + return vars_.find(varName) != vars_.end(); +} + Variable* SymbolTable::newVariable(const std::string& name) { VLOG(1) << "New variable for: " << name; DCHECK(vars_.find(name) == vars_.end()); diff --git a/src/graph/context/Symbols.h b/src/graph/context/Symbols.h index bcf3b44b815..84a497e11ba 100644 --- a/src/graph/context/Symbols.h +++ b/src/graph/context/Symbols.h @@ -56,6 +56,8 @@ class SymbolTable final { explicit SymbolTable(ObjectPool* objPool, ExecutionContext* ectx) : objPool_(DCHECK_NOTNULL(objPool)), ectx_(DCHECK_NOTNULL(ectx)) {} + bool existsVar(const std::string& varName) const; + Variable* newVariable(const std::string& name); bool readBy(const std::string& varName, PlanNode* node); diff --git a/src/graph/validator/AssignmentValidator.cpp b/src/graph/validator/AssignmentValidator.cpp index 1d4ee9e34f9..b554af92407 100644 --- a/src/graph/validator/AssignmentValidator.cpp +++ b/src/graph/validator/AssignmentValidator.cpp @@ -17,6 +17,9 @@ Status AssignmentValidator::validateImpl() { auto outputs = validator_->outputCols(); var_ = *assignSentence->var(); + if (qctx_->symTable()->existsVar(var_)) { + return Status::SemanticError("Variable `%s' already exists", var_.c_str()); + } vctx_->registerVariable(var_, std::move(outputs)); return Status::OK(); } diff --git a/tests/tck/features/aggregate/Agg.feature b/tests/tck/features/aggregate/Agg.feature index 2f3e7a62f59..29034fc22f0 100644 --- a/tests/tck/features/aggregate/Agg.feature +++ b/tests/tck/features/aggregate/Agg.feature @@ -75,6 +75,71 @@ Feature: Basic Aggregate and GroupBy Then the result should be, in any order, with relax comparison: | COUNT(*) | | 56 | + When executing query: + """ + UNWIND [1,2,NULL] AS a + RETURN COUNT(*), COUNT(a) + """ + Then the result should be, in any order, with relax comparison: + | COUNT(*) | COUNT(a) | + | 3 | 2 | + When executing query: + """ + UNWIND [1,2,NULL] AS a + RETURN SUM(a), AVG(a), MIN(a), MAX(a), COLLECT(a) + """ + Then the result should be, in any order, with relax comparison: + | SUM(a) | AVG(a) | MIN(a) | MAX(a) | COLLECT(a) | + | 3 | 1.5 | 1 | 2 | [1,2] | + When executing query: + """ + UNWIND [1,2,NULL,2] AS a + RETURN COLLECT(a), COLLECT(DISTINCT a) + """ + Then the result should be, in any order, with relax comparison: + | COLLECT(a) | COLLECT(distinct a) | + | [1,2,2] | [1,2] | + When executing query: + """ + UNWIND [NULL,NULL,NULL] AS a + RETURN SUM(a), AVG(a), MIN(a), MAX(a), COLLECT(a), COLLECT(DISTINCT a) + """ + Then the result should be, in any order, with relax comparison: + | SUM(a) | AVG(a) | MIN(a) | MAX(a) | COLLECT(a) | COLLECT(distinct a) | + | 0 | NULL | NULL | NULL | [] | [] | + # one group key + When executing query: + """ + MATCH (v:player)-[e:like]->(v2) WHERE id(v) IN ["Tony Parker", "Tim Duncan", "LaMarcus Aldridge"] + RETURN v, COUNT(*), COUNT(v2), COUNT(DISTINCT v2), MIN(v2.player.age), MAX(e.likeness), SUM(e.likeness), COLLECT(v2), COLLECT(DISTINCT v2) + ORDER BY v + """ + Then the result should be, in any order, with relax comparison: + | v | COUNT(*) | COUNT(v2) | COUNT(distinct v2) | MIN(v2.player.age) | MAX(e.likeness) | SUM(e.likeness) | COLLECT(v2) | COLLECT(distinct v2) | + | ("LaMarcus Aldridge") | 2 | 2 | 2 | 36 | 75 | 150 | [("Tim Duncan"), ("Tony Parker")] | [("Tim Duncan"), ("Tony Parker")] | + | ("Tim Duncan") | 2 | 2 | 2 | 36 | 95 | 190 | [("Manu Ginobili"), ("Tony Parker") ] | [("Manu Ginobili"), ("Tony Parker")] | + | ("Tony Parker") | 3 | 3 | 3 | 33 | 95 | 280 | [("LaMarcus Aldridge"), ("Manu Ginobili"), ("Tim Duncan")] | [("LaMarcus Aldridge"), ("Manu Ginobili"), ("Tim Duncan")] | + # multi group keys + When executing query: + """ + MATCH (v:player)-[e:like*1..3]->(v2)-[e2:like]->(v3) WHERE id(v) IN ["Tony Parker", "Tim Duncan", "LaMarcus Aldridge"] + RETURN v, v2, COUNT(*), COUNT(id(v3)), COUNT(DISTINCT id(v3)), MIN(v3.player.age), MAX(e2.likeness), SUM(e2.likeness), COLLECT(id(v3)), COLLECT(DISTINCT id(v3)) + ORDER BY v + """ + Then the result should be, in any order, with relax comparison: + | v | v2 | COUNT(*) | COUNT(id(v3)) | COUNT(distinct id(v3)) | MIN(v3.player.age) | MAX(e2.likeness) | SUM(e2.likeness) | COLLECT(id(v3)) | COLLECT(distinct id(v3)) | + | ("LaMarcus Aldridge") | ("LaMarcus Aldridge") | 2 | 2 | 2 | 36 | 75 | 150 | ["Tim Duncan", "Tony Parker"] | ["Tim Duncan", "Tony Parker"] | + | ("LaMarcus Aldridge") | ("Manu Ginobili") | 4 | 4 | 1 | 42 | 90 | 360 | ["Tim Duncan", "Tim Duncan", "Tim Duncan", "Tim Duncan"] | ["Tim Duncan"] | + | ("LaMarcus Aldridge") | ("Tony Parker") | 8 | 8 | 3 | 33 | 95 | 745 | ["LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge", "Manu Ginobili"] | ["LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan"] | + | ("LaMarcus Aldridge") | ("Tim Duncan") | 10 | 10 | 2 | 36 | 95 | 950 | ["Manu Ginobili", "Tony Parker", "Manu Ginobili", "Tony Parker", "Tony Parker", "Manu Ginobili", "Manu Ginobili", "Tony Parker", "Manu Ginobili", "Tony Parker"] | ["Manu Ginobili", "Tony Parker"] | + | ("Tim Duncan") | ("Manu Ginobili") | 3 | 3 | 1 | 42 | 90 | 270 | ["Tim Duncan", "Tim Duncan", "Tim Duncan"] | ["Tim Duncan"] | + | ("Tim Duncan") | ("LaMarcus Aldridge") | 2 | 2 | 2 | 36 | 75 | 150 | ["Tim Duncan", "Tony Parker"] | ["Tim Duncan", "Tony Parker"] | + | ("Tim Duncan") | ("Tim Duncan") | 4 | 4 | 2 | 36 | 95 | 380 | ["Tony Parker", "Manu Ginobili", "Manu Ginobili", "Manu Ginobili"] | ["Tony Parker", "Manu Ginobili"] | + | ("Tim Duncan") | ("Tony Parker") | 8 | 8 | 3 | 33 | 95 | 750 | ["LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan", "Manu Ginobili", "Tim Duncan"] | ["LaMarcus Aldridge", "Manu Ginobili", "Tim Duncan"] | + | ("Tony Parker") | ("LaMarcus Aldridge") | 4 | 4 | 2 | 36 | 75 | 300 | ["Tim Duncan", "Tony Parker", "Tim Duncan", "Tony Parker"] | ["Tim Duncan", "Tony Parker"] | + | ("Tony Parker") | ("Tim Duncan") | 9 | 9 | 2 | 36 | 95 | 855 | ["Manu Ginobili", "Tony Parker", "Manu Ginobili", "Tony Parker", "Manu Ginobili", "Tony Parker", "Manu Ginobili", "Tony Parker", "Tony Parker"] | ["Manu Ginobili", "Tony Parker"] | + | ("Tony Parker") | ("Tony Parker") | 8 | 8 | 3 | 33 | 95 | 750 | ["Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge", "Manu Ginobili", "Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge", "Tim Duncan"] | ["Manu Ginobili", "Tim Duncan", "LaMarcus Aldridge"] | + | ("Tony Parker") | ("Manu Ginobili") | 5 | 5 | 1 | 42 | 90 | 450 | ["Tim Duncan", "Tim Duncan", "Tim Duncan", "Tim Duncan", "Tim Duncan"] | ["Tim Duncan"] | Scenario: [1] Basic GroupBy When executing query: diff --git a/tests/tck/features/go/GroupbyLimit.feature b/tests/tck/features/go/GroupbyLimit.feature index 6a996417c21..9c33a10be3f 100644 --- a/tests/tck/features/go/GroupbyLimit.feature +++ b/tests/tck/features/go/GroupbyLimit.feature @@ -132,6 +132,26 @@ Feature: Groupby & limit Sentence """ Then the result should be, in any order, with relax comparison: | name | + When executing query: + """ + GO FROM "Danny Green" OVER serve YIELD $$.team.name AS name | LIMIT 3.0, 2 + """ + Then a SyntaxError should be raised at runtime: syntax error near `3.0' + When executing query: + """ + GO FROM "Danny Green" OVER serve YIELD $$.team.name AS name | LIMIT 3, 2.0 + """ + Then a SyntaxError should be raised at runtime: syntax error near `2.0' + When executing query: + """ + GO FROM "Danny Green" OVER serve YIELD $$.team.name AS name | LIMIT 1+2 + """ + Then a SyntaxError should be raised at runtime: syntax error near `+2' + When executing query: + """ + GO FROM "Danny Green" OVER serve YIELD $$.team.name AS name | LIMIT 3, 1+1 + """ + Then a SyntaxError should be raised at runtime: syntax error near `+1' Scenario: OFFSET 0 When executing query: diff --git a/tests/tck/features/go/Orderby.feature b/tests/tck/features/go/Orderby.feature index c0ae999a597..b9494d28b38 100644 --- a/tests/tck/features/go/Orderby.feature +++ b/tests/tck/features/go/Orderby.feature @@ -211,3 +211,23 @@ Feature: Orderby Sentence GO FROM "Boris Diaw" OVER serve YIELD $^.player.name as team, serve.start_year as start, $$.team.name as team | ORDER BY $-.team """ Then a SemanticError should be raised at runtime: + + Scenario: Order by with null + When executing query: + """ + UNWIND [3, NULL, 1] AS a + UNWIND [1, 4, NULL] AS b + RETURN a, b + ORDER BY a ASC, b DESC + """ + Then the result should be, in order, with relax comparison: + | a | b | + | 1 | NULL | + | 1 | 4 | + | 1 | 1 | + | 3 | NULL | + | 3 | 4 | + | 3 | 1 | + | NULL | NULL | + | NULL | 4 | + | NULL | 1 | diff --git a/tests/tck/features/match/PipeAndVariable.feature b/tests/tck/features/match/PipeAndVariable.feature index 68abc31edc2..6a4cd19f813 100644 --- a/tests/tck/features/match/PipeAndVariable.feature +++ b/tests/tck/features/match/PipeAndVariable.feature @@ -1,11 +1,142 @@ # Copyright (c) 2021 vesoft inc. All rights reserved. # # This source code is licensed under Apache 2.0 License. -Feature: Pipe or use variable to store the lookup results +Feature: Pipe/Variable Background: Given a graph with space named "nba" + Scenario: Variable + When executing query: + """ + $v1 = GO FROM "Tony Parker" OVER like YIELD id($$) AS dst, $^.player.age AS age + """ + Then the result should be, in any order, with relax comparison: + | dst | age | + | "LaMarcus Aldridge" | 36 | + | "Manu Ginobili" | 36 | + | "Tim Duncan" | 36 | + When executing query: + """ + $v1 = GO FROM "Tony Parker" OVER like YIELD id($$) AS dst, $^.player.age AS age; + YIELD $v1 + """ + Then a SyntaxError should be raised at runtime: Direct output of variable is prohibited near `$v1' + When executing query: + """ + $v1 = GO FROM "Tony Parker" OVER like YIELD id($$) AS dst, $^.player.age AS age; + YIELD $v1.age + """ + Then the result should be, in any order, with relax comparison: + | $v1.age | + | 36 | + | 36 | + | 36 | + When executing query: + """ + $v1 = FETCH PROP ON player "Tony Parker" + YIELD properties(Vertex) AS props, properties(Vertex).name AS name, properties(Vertex).age AS age + """ + Then the result should be, in any order, with relax comparison: + | props | name | age | + | {age: 36, name: "Tony Parker"} | "Tony Parker" | 36 | + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + $v2 = YIELD "Tim Duncan" AS b; + GO FROM $v1.a OVER like WHERE $v1.a > $v2.b YIELD id($$) AS dst; + """ + Then a SemanticError should be raised at runtime: Multiple variable property is not supported in WHERE or YIELD + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + GO FROM "Tim Duncan" OVER like WHERE id($$) != $v1.a + YIELD id($$) AS dst + """ + Then a SemanticError should be raised at runtime: A variable must be referred in FROM before used in WHERE or YIELD + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + GO FROM "Tim Duncan" OVER like WHERE id($$) != $v1.a + YIELD id($$) AS dst + """ + Then a SemanticError should be raised at runtime: A variable must be referred in FROM before used in WHERE or YIELD + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + GO FROM "Tim Duncan" OVER like + YIELD id($$) AS dst, $v1.a AS dst2 + """ + Then a SemanticError should be raised at runtime: A variable must be referred in FROM before used in WHERE or YIELD + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + GO FROM $v1.a OVER like WHERE id($$) != $v1.a + YIELD id($$) AS dst, $v1.a AS dst2 + """ + Then the result should be, in any order, with relax comparison: + | dst | dst2 | + | "LaMarcus Aldridge" | "Tony Parker" | + | "Manu Ginobili" | "Tony Parker" | + | "Tim Duncan" | "Tony Parker" | + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + $v1 = YIELD "Tim Duncan" AS a; + """ + Then a SemanticError should be raised at runtime: Variable `v1' already exists + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + $v2 = YIELD $v1.a AS a; + """ + Then the result should be, in any order, with relax comparison: + | a | + | "Tony Parker" | + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + $v2 = YIELD $v1.a AS a; + YIELD $v1.a AS a UNION ALL YIELD $v2.a AS a + """ + Then the result should be, in any order, with relax comparison: + | a | + | "Tony Parker" | + | "Tony Parker" | + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + $v2 = YIELD $v1.a AS a; + YIELD $v1.a, $v2.a + """ + Then a SemanticError should be raised at runtime: Only one variable allowed to use. + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + FETCH PROP ON player $v1.a YIELD player.name AS name + """ + Then the result should be, in any order, with relax comparison: + | name | + | "Tony Parker" | + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + FETCH PROP ON player $v1.a YIELD player.name AS name, $v1.a AS a + """ + Then a SemanticError should be raised at runtime: unsupported input/variable property expression in yield. + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + LOOKUP ON player WHERE player.name == $v1.a YIELD player.name AS name, $v1.a + """ + Then a SemanticError should be raised at runtime: '$v1.a' is not an evaluable expression. + When executing query: + """ + $v1 = YIELD "Tony Parker" AS a; + LOOKUP ON player WHERE player.name == "Tim Duncan" YIELD player.name AS name, $v1.a + """ + Then a SemanticError should be raised at runtime: unsupport input/variable property expression in yield. + @skip Scenario: pipe lookup results When executing query: diff --git a/tests/tck/features/set/Set.feature b/tests/tck/features/set/Set.feature index ae952150c44..6d962287a81 100644 --- a/tests/tck/features/set/Set.feature +++ b/tests/tck/features/set/Set.feature @@ -3,6 +3,98 @@ # This source code is licensed under Apache 2.0 License. Feature: Set Test + Scenario: Basic + Given a graph with space named "nba" + When executing query: + """ + RETURN 1 AS a, 2 AS b + UNION + RETURN 3 AS a + """ + Then an SemanticError should be raised at runtime: number of columns to UNION/INTERSECT/MINUS must be same + When executing query: + """ + RETURN 1 AS a, 2 AS b + UNION ALL + RETURN 3 AS a + """ + Then an SemanticError should be raised at runtime: number of columns to UNION/INTERSECT/MINUS must be same + When executing query: + """ + RETURN 1 AS a, 2 AS b + INTERSECT + RETURN 3 AS a + """ + Then an SemanticError should be raised at runtime: number of columns to UNION/INTERSECT/MINUS must be same + When executing query: + """ + RETURN 1 AS a, 2 AS b + UNION DISTINCT + RETURN 3 AS a, 4 AS c + """ + Then an SemanticError should be raised at runtime: different column names to UNION/INTERSECT/MINUS are not supported + When executing query: + """ + RETURN 1 AS a, 2 AS b + INTERSECT + RETURN 3 AS a, 4 AS c + """ + Then an SemanticError should be raised at runtime: different column names to UNION/INTERSECT/MINUS are not supported + When executing query: + """ + RETURN 1 AS a, 2 AS b + UNION + RETURN 3 AS b, 4 AS a + """ + Then an SemanticError should be raised at runtime: different column names to UNION/INTERSECT/MINUS are not supported + When executing query: + """ + RETURN 1 AS a, 2 AS b + INTERSECT + RETURN 3 AS b, 4 AS a + """ + Then an SemanticError should be raised at runtime: different column names to UNION/INTERSECT/MINUS are not supported + When executing query: + """ + UNWIND [1,2] AS a RETURN a + UNION ALL + UNWIND [2] AS a RETURN a + """ + Then the result should be, in any order: + | a | + | 1 | + | 2 | + | 2 | + When executing query: + """ + UNWIND [1,2] AS a RETURN a + UNION + UNWIND [2] AS a RETURN a + """ + Then the result should be, in any order: + | a | + | 1 | + | 2 | + + # cypher doesn't support intersect + # When executing query: + # """ + # UNWIND [1,2] AS a RETURN a + # INTERSECT + # RETURN 2 AS a + # """ + # Then the result should be, in any order: + # | a | + # | 1 | + # When executing query: + # """ + # UNWIND [1,2,3] AS a RETURN a, 100 + # INTERSECT + # RETURN 2 AS a, 100 + # """ + # Then the result should be, in any order: + # | a | 100 | + # | 2 | 100 | Scenario: Union All Given a graph with space named "nba" When executing query: