diff --git a/src/common/datatypes/Edge.cpp b/src/common/datatypes/Edge.cpp index d32dd8a9183..c5d2f3464b4 100644 --- a/src/common/datatypes/Edge.cpp +++ b/src/common/datatypes/Edge.cpp @@ -107,13 +107,7 @@ bool Edge::operator<(const Edge& rhs) const { } bool Edge::operator==(const Edge& rhs) const { - if (type != rhs.type && type != -rhs.type) { - return false; - } - if (type == rhs.type) { - return src == rhs.src && dst == rhs.dst && ranking == rhs.ranking && props == rhs.props; - } - return src == rhs.dst && dst == rhs.src && ranking == rhs.ranking && props == rhs.props; + return keyEqual(rhs); } void Edge::reverse() { diff --git a/src/common/datatypes/Vertex.h b/src/common/datatypes/Vertex.h index 41f4cfab554..29ef6f83753 100644 --- a/src/common/datatypes/Vertex.h +++ b/src/common/datatypes/Vertex.h @@ -94,11 +94,11 @@ struct Vertex { Vertex& operator=(const Vertex& rhs); bool operator==(const Vertex& rhs) const { - return vid == rhs.vid && tags == rhs.tags; + return vid == rhs.vid; } bool operator!=(const Vertex& rhs) const { - return vid != rhs.vid || tags != rhs.tags; + return !(*this == rhs); } bool operator<(const Vertex& rhs) const; diff --git a/src/common/expression/test/TestBase.h b/src/common/expression/test/TestBase.h index 42ff3ca8bfb..988d0fd4bc2 100644 --- a/src/common/expression/test/TestBase.h +++ b/src/common/expression/test/TestBase.h @@ -60,7 +60,7 @@ class ExpressionTest : public ::testing::Test { protected: void testExpr(const std::string &exprSymbol, Value expected) { - std::string query = "RETURN " + exprSymbol; + std::string query = "YIELD " + exprSymbol; nebula::graph::QueryContext queryCtxt; nebula::GQLParser gParser(&queryCtxt); auto result = gParser.parse(query); @@ -86,7 +86,7 @@ class ExpressionTest : public ::testing::Test { } void testToString(const std::string &exprSymbol, const char *expected) { - std::string query = "RETURN " + exprSymbol; + std::string query = "YIELD " + exprSymbol; nebula::graph::QueryContext queryCtxt; nebula::GQLParser gParser(&queryCtxt); auto result = gParser.parse(query); @@ -106,7 +106,7 @@ class ExpressionTest : public ::testing::Test { } void testFunction(const char *name, const std::vector &args, const Value &expected) { - std::string query = "RETURN " + std::string(name) + "("; + std::string query = "YIELD " + std::string(name) + "("; for (const auto &i : args) { query += i.toString() + ","; } diff --git a/src/graph/context/ast/CypherAstContext.h b/src/graph/context/ast/CypherAstContext.h index bb89302123b..e0fb879b2c9 100644 --- a/src/graph/context/ast/CypherAstContext.h +++ b/src/graph/context/ast/CypherAstContext.h @@ -158,7 +158,7 @@ struct YieldClauseContext final : CypherClauseContextBase { std::vector paths; bool distinct{false}; - const YieldColumns* yieldColumns{nullptr}; + YieldColumns* yieldColumns{nullptr}; bool hasAgg_{false}; bool needGenProject_{false}; diff --git a/src/graph/validator/MatchValidator.cpp b/src/graph/validator/MatchValidator.cpp index e5936943179..56c2505deba 100644 --- a/src/graph/validator/MatchValidator.cpp +++ b/src/graph/validator/MatchValidator.cpp @@ -1067,13 +1067,17 @@ Status MatchValidator::checkAlias( // Validate yield columns. // Fill outputs of whole sentence. -Status MatchValidator::buildOutputs(const YieldColumns *yields) { +Status MatchValidator::buildOutputs(YieldColumns *yields) { for (auto *col : yields->columns()) { auto colName = col->name(); auto typeStatus = deduceExprType(col->expr()); NG_RETURN_IF_ERROR(typeStatus); auto type = typeStatus.value(); outputs_.emplace_back(colName, type); + + auto foldStatus = ExpressionUtils::foldConstantExpr(col->expr()); + NG_RETURN_IF_ERROR(foldStatus); + col->setExpr(foldStatus.value()); } return Status::OK(); } diff --git a/src/graph/validator/MatchValidator.h b/src/graph/validator/MatchValidator.h index d9ca0cba82e..f1e9f5166d5 100644 --- a/src/graph/validator/MatchValidator.h +++ b/src/graph/validator/MatchValidator.h @@ -87,7 +87,7 @@ class MatchValidator final : public Validator { Status checkAlias(const Expression *refExpr, const std::unordered_map &aliasesAvailable) const; - Status buildOutputs(const YieldColumns *yields); + Status buildOutputs(YieldColumns *yields); StatusOr makeEdgeSubFilter(MapExpression *map) const; diff --git a/src/parser/parser.yy b/src/parser/parser.yy index cb8e6c0f28d..cb9344222d4 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -1644,14 +1644,6 @@ yield_sentence s->setWhereClause($4); $$ = s; } - | KW_RETURN yield_columns { - auto *s = new YieldSentence($2); - $$ = s; - } - | KW_RETURN KW_DISTINCT yield_columns { - auto *s = new YieldSentence($3, true); - $$ = s; - } ; unwind_clause @@ -1728,7 +1720,10 @@ reading_with_clauses ; match_sentence - : reading_clauses match_return { + : match_return { + $$ = new MatchSentence(new MatchClauseList(), $1); + } + | reading_clauses match_return { $$ = new MatchSentence($1, $2); } | reading_with_clauses match_return { @@ -2969,6 +2964,9 @@ match_sentences s->setDistinct(); $$ = s; } + | match_sentences KW_INTERSECT match_sentence { $$ = new SetSentence($1, SetSentence::INTERSECT, $3); } + | match_sentences KW_MINUS match_sentence { $$ = new SetSentence($1, SetSentence::MINUS, $3); } + ; assignment_sentence : VARIABLE ASSIGN set_sentence { diff --git a/tests/tck/features/bugfix/ListSlicingWithNull.feature b/tests/tck/features/bugfix/ListSlicingWithNull.feature index b234c42c601..409ed52b5bd 100644 --- a/tests/tck/features/bugfix/ListSlicingWithNull.feature +++ b/tests/tck/features/bugfix/ListSlicingWithNull.feature @@ -7,7 +7,7 @@ Feature: Test yield constant after pipe Scenario: List slicing with null range When executing query: """ - return [1, 2, 3][null..1] as a + yield [1, 2, 3][null..1] as a """ Then the result should be, in any order: | a | diff --git a/tests/tck/features/expression/Case.feature b/tests/tck/features/expression/Case.feature index f4dad8a1b9c..fc662f6b05d 100644 --- a/tests/tck/features/expression/Case.feature +++ b/tests/tck/features/expression/Case.feature @@ -298,7 +298,7 @@ Feature: Case Expression Scenario: Using the return value of case expr as an input When executing query: """ - RETURN CASE WHEN true THEN "Tim Duncan" ELSE "ABC" END AS a | GO FROM $-.a OVER like YIELD like._dst; + YIELD CASE WHEN true THEN "Tim Duncan" ELSE "ABC" END AS a | GO FROM $-.a OVER like YIELD like._dst; """ Then the result should be, in order: | like._dst | diff --git a/tests/tck/features/expression/function/Mathematical.feature b/tests/tck/features/expression/function/Mathematical.feature index cecdd0e40e5..d46caee3bbe 100644 --- a/tests/tck/features/expression/function/Mathematical.feature +++ b/tests/tck/features/expression/function/Mathematical.feature @@ -3,6 +3,9 @@ # This source code is licensed under Apache 2.0 License. Feature: Mathematical function Expression + Background: + Given a graph with space named "nba" + Scenario: bit functions When executing query: """ diff --git a/tests/tck/features/function/coalesce.feature b/tests/tck/features/function/coalesce.feature index 0391c892f49..49403543eb5 100644 --- a/tests/tck/features/function/coalesce.feature +++ b/tests/tck/features/function/coalesce.feature @@ -1,7 +1,10 @@ +# Copyright (c) 2022 vesoft inc. All rights reserved. +# +# This source code is licensed under Apache 2.0 License. Feature: Coalesce Function Background: - Test coalesce function + Given a graph with space named "nba" Scenario: test normal case When executing query: diff --git a/tests/tck/features/set/Set.feature b/tests/tck/features/set/Set.feature index 6d962287a81..44f8a93b52e 100644 --- a/tests/tck/features/set/Set.feature +++ b/tests/tck/features/set/Set.feature @@ -75,26 +75,26 @@ Feature: Set Test | 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 | + | 2 | + 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 | - # 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: @@ -257,6 +257,57 @@ Feature: Set Test Then the result should be, in any order: | $^.player.name | serve.start_year | $$.team.name | | "Manu Ginobili" | 2002 | "Spurs" | + When executing query: + """ + MATCH (v:player) RETURN v ORDER BY v LIMIT 3 + MINUS + MATCH (v:player) RETURN v ORDER BY v LIMIT 3 + """ + Then the result should be, in any order, with relax comparison: + | v | + When executing query: + """ + MATCH (v:player) + WITH v.player.name AS v + RETURN v ORDER BY v LIMIT 3 + MINUS + UNWIND ["Tony Parker", "Ben Simmons"] AS v + RETURN v + """ + Then the result should be, in any order, with relax comparison: + | v | + | "Amar'e Stoudemire" | + | "Aron Baynes" | + When executing query: + """ + UNWIND [1,2,3] AS a RETURN a + MINUS + UNWIND [2,3,4] AS a RETURN a + """ + Then the result should be, in any order, with relax comparison: + | a | + | 1 | + When executing query: + """ + UNWIND [1,2,3] AS a RETURN a + MINUS + RETURN 4 AS a + """ + Then the result should be, in any order, with relax comparison: + | a | + | 1 | + | 2 | + | 3 | + When executing query: + """ + UNWIND [1,2,3] AS a RETURN a + MINUS + RETURN 2 AS a + """ + Then the result should be, in any order, with relax comparison: + | a | + | 1 | + | 3 | Scenario: Intersect Given a graph with space named "nba" @@ -271,6 +322,56 @@ Feature: Set Test | $^.player.name | serve.start_year | $$.team.name | | "Tony Parker" | 1999 | "Spurs" | | "Tony Parker" | 2018 | "Hornets" | + When executing query: + """ + MATCH (v:player) + WITH v.player.name AS v + RETURN v ORDER BY v LIMIT 3 + INTERSECT + MATCH (v:player) + WITH v.player.name AS v + RETURN v ORDER BY v LIMIT 3 + """ + Then the result should be, in any order, with relax comparison: + | v | + | "Amar'e Stoudemire" | + | "Aron Baynes" | + | "Ben Simmons" | + When executing query: + """ + MATCH (v:player) + RETURN v ORDER BY v LIMIT 3 + INTERSECT + MATCH (v:player) + RETURN v ORDER BY v LIMIT 3 + """ + Then the result should be, in any order, with relax comparison: + | v | + | ("Amar'e Stoudemire") | + | ("Aron Baynes") | + | ("Ben Simmons") | + When executing query: + """ + MATCH (v:player) + WITH v.player.name AS v + RETURN v ORDER BY v LIMIT 3 + INTERSECT + UNWIND ["Tony Parker", "Ben Simmons"] AS v + RETURN v + """ + Then the result should be, in any order, with relax comparison: + | v | + | "Ben Simmons" | + When executing query: + """ + UNWIND [1,2,3] AS a RETURN a + INTERSECT + UNWIND [2,3,4] AS a RETURN a + """ + Then the result should be, in any order, with relax comparison: + | a | + | 2 | + | 3 | Scenario: Mix Given a graph with space named "nba" diff --git a/tests/tck/features/yield/return.feature b/tests/tck/features/yield/return.feature index d18cd814ea8..11070dd6974 100644 --- a/tests/tck/features/yield/return.feature +++ b/tests/tck/features/yield/return.feature @@ -4,7 +4,7 @@ Feature: Return Background: - Given an empty graph + Given a graph with space named "nba" Scenario: base When executing query: @@ -79,4 +79,4 @@ Feature: Return """ RETURN name """ - Then a SemanticError should be raised at runtime: Invalid label identifiers: name + Then a SemanticError should be raised at runtime: Alias used but not defined: `name'