diff --git a/src/parser/parser.yy b/src/parser/parser.yy index 997e9926b669f06225d5683adf4261d693084534..3f2ec9b9b97e180acf1760f5f14202bc1a275356 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -777,8 +777,9 @@ predicate_expression delete $3; } | KW_EXISTS L_PAREN expression R_PAREN { - if ($3->kind() != Expression::Kind::kLabelAttribute && $3->kind() != Expression::Kind::kAttribute) { - throw nebula::GraphParser::syntax_error(@3, "The exists only accept LabelAttribe OR Attribute"); + if ($3->kind() != Expression::Kind::kLabelAttribute && $3->kind() != Expression::Kind::kAttribute && + $3->kind() != Expression::Kind::kSubscript) { + throw nebula::GraphParser::syntax_error(@3, "The exists only accept LabelAttribe, Attribute and Subscript"); } $$ = new PredicateExpression(new std::string("exists"), nullptr, $3, nullptr); } diff --git a/tests/tck/features/expression/Predicate.feature b/tests/tck/features/expression/Predicate.feature index 360e848190cb6a6127d8c8cb8dcfc61cf6411ca3..2df3bc317eb28c4e35f0e309cca7251ca1691ebb 100644 --- a/tests/tck/features/expression/Predicate.feature +++ b/tests/tck/features/expression/Predicate.feature @@ -49,6 +49,118 @@ Feature: Predicate | "Manu Ginobili" | 95 | | "Tim Duncan" | 95 | + Scenario: exists with dynamic map in MATCH + Given an empty graph + And load "nba" csv data to a new space + Given having executed: + """ + CREATE TAG INDEX bachelor_name_index ON bachelor(name(20)); + """ + And wait 6 seconds + When submit a job: + """ + REBUILD TAG INDEX bachelor_name_index + """ + Then wait the job to finish + When executing query: + """ + MATCH (n:bachelor) WHERE EXISTS(n['name']) return n AS bachelor + """ + Then the result should be, in order: + | bachelor | + | ("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) | + When executing query: + """ + MATCH(n:player) WHERE EXISTS(n['name']) + RETURN n.name AS name ORDER BY name LIMIT 10 + """ + Then the result should be, in order: + | name | + | "Amar'e Stoudemire" | + | "Aron Baynes" | + | "Ben Simmons" | + | "Blake Griffin" | + | "Boris Diaw" | + | "Carmelo Anthony" | + | "Chris Paul" | + | "Cory Joseph" | + | "Damian Lillard" | + | "Danny Green" | + When executing query: + """ + MATCH(v:player)-[e:like|serve]-(v2) WHERE EXISTS(e['likeness']) RETURN DISTINCT v2 + """ + Then the result should be, in any order: + | v2 | + | ("Dirk Nowitzki" :player{age: 40, name: "Dirk Nowitzki"}) | + | ("Steve Nash" :player{age: 45, name: "Steve Nash"}) | + | ("Vince Carter" :player{age: 42, name: "Vince Carter"}) | + | ("Rudy Gay" :player{age: 32, name: "Rudy Gay"}) | + | ("Kobe Bryant" :player{age: 40, name: "Kobe Bryant"}) | + | ("Grant Hill" :player{age: 46, name: "Grant Hill"}) | + | ("Jason Kidd" :player{age: 45, name: "Jason Kidd"}) | + | ("Yao Ming" :player{age: 38, name: "Yao Ming"}) | + | ("Tracy McGrady" :player{age: 39, name: "Tracy McGrady"}) | + | ("Dejounte Murray" :player{age: 29, name: "Dejounte Murray"}) | + | ("Luka Doncic" :player{age: 20, name: "Luka Doncic"}) | + | ("Russell Westbrook" :player{age: 30, name: "Russell Westbrook"}) | + | ("Tony Parker" :player{age: 36, name: "Tony Parker"}) | + | ("Chris Paul" :player{age: 33, name: "Chris Paul"}) | + | ("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) | + | ("LaMarcus Aldridge" :player{age: 33, name: "LaMarcus Aldridge"}) | + | ("Carmelo Anthony" :player{age: 34, name: "Carmelo Anthony"}) | + | ("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"}) | + | ("Danny Green" :player{age: 31, name: "Danny Green"}) | + | ("Paul George" :player{age: 28, name: "Paul George"}) | + | ("Dwyane Wade" :player{age: 37, name: "Dwyane Wade"}) | + | ("Kyrie Irving" :player{age: 26, name: "Kyrie Irving"}) | + | ("Ray Allen" :player{age: 43, name: "Ray Allen"}) | + | ("James Harden" :player{age: 29, name: "James Harden"}) | + | ("Marco Belinelli" :player{age: 32, name: "Marco Belinelli"}) | + | ("LeBron James" :player{age: 34, name: "LeBron James"}) | + | ("Rajon Rondo" :player{age: 33, name: "Rajon Rondo"}) | + | ("Tiago Splitter" :player{age: 34, name: "Tiago Splitter"}) | + | ("Shaquile O'Neal" :player{age: 47, name: "Shaquile O'Neal"}) | + | ("Boris Diaw" :player{age: 36, name: "Boris Diaw"}) | + | ("Aron Baynes" :player{age: 32, name: "Aron Baynes"}) | + | ("Paul Gasol" :player{age: 38, name: "Paul Gasol"}) | + | ("Kristaps Porzingis" :player{age: 23, name: "Kristaps Porzingis"}) | + | ("Klay Thompson" :player{age: 29, name: "Klay Thompson"}) | + | ("Stephen Curry" :player{age: 31, name: "Stephen Curry"}) | + | ("Kyle Anderson" :player{age: 25, name: "Kyle Anderson"}) | + | ("Kevin Durant" :player{age: 30, name: "Kevin Durant"}) | + | ("Amar'e Stoudemire" :player{age: 36, name: "Amar'e Stoudemire"}) | + | ("Marc Gasol" :player{age: 34, name: "Marc Gasol"}) | + | ("Ben Simmons" :player{age: 22, name: "Ben Simmons"}) | + | ("JaVale McGee" :player{age: 31, name: "JaVale McGee"}) | + | ("Joel Embiid" :player{age: 25, name: "Joel Embiid"}) | + | ("Blake Griffin" :player{age: 30, name: "Blake Griffin"}) | + | ("Damian Lillard" :player{age: 28, name: "Damian Lillard"}) | + When executing query: + """ + MATCH(n:player) WHERE EXISTS("abc") + RETURN n.name AS name ORDER BY name LIMIT 10 + """ + Then a SyntaxError should be raised at runtime: The exists only accept LabelAttribe, Attribute and Subscript + Then drop the used space + + Scenario: exists with dynamic map in variable length MATCH + Given a graph with space named "nba" + When executing query: + """ + MATCH(v:player{name:"Tim Duncan"})-[e:like|serve*2]->(v2) + RETURN DISTINCT e, ALL(e IN e WHERE EXISTS(e['likeness'])) + """ + Then the result should be, in any order: + | e | all(e IN e WHERE exists(e["likeness"])) | + | [[:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}], [:serve "Tony Parker"->"Spurs" @0 {end_year: 2018, start_year: 1999}]] | false | + | [[:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}], [:serve "Tony Parker"->"Hornets" @0 {end_year: 2019, start_year: 2018}]] | false | + | [[:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}], [:like "Tony Parker"->"Tim Duncan" @0 {likeness: 95}]] | true | + | [[:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}], [:like "Manu Ginobili"->"Tim Duncan" @0 {likeness: 90}]] | true | + | [[:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}], [:serve "Manu Ginobili"->"Spurs" @0 {end_year: 2018, start_year: 2002}]] | false | + | [[:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}], [:like "Tony Parker"->"LaMarcus Aldridge" @0 {likeness: 90}]] | true | + | [[:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}], [:like "Tony Parker"->"Manu Ginobili" @0 {likeness: 95}]] | true | + Scenario: use a predicate in MATCH Given a graph with space named "nba" When executing query: