diff --git a/src/graph/validator/OrderByValidator.cpp b/src/graph/validator/OrderByValidator.cpp index 51887b2b5a8..9187395ac14 100644 --- a/src/graph/validator/OrderByValidator.cpp +++ b/src/graph/validator/OrderByValidator.cpp @@ -6,7 +6,6 @@ #include "graph/validator/OrderByValidator.h" -#include "common/expression/LabelExpression.h" #include "graph/planner/plan/Query.h" #include "parser/TraverseSentences.h" @@ -14,26 +13,46 @@ namespace nebula { namespace graph { Status OrderByValidator::validateImpl() { auto sentence = static_cast(sentence_); - outputs_ = inputCols(); auto &factors = sentence->factors(); - auto *pool = qctx_->objPool(); for (auto &factor : factors) { - if (factor->expr()->kind() == Expression::Kind::kLabel) { - auto *label = static_cast(factor->expr()); - auto *expr = InputPropertyExpression::make(pool, label->name()); - factor->setExpr(expr); - } - if (factor->expr()->kind() != Expression::Kind::kInputProperty) { + if (factor->expr()->kind() == Expression::Kind::kInputProperty) { + auto expr = static_cast(factor->expr()); + NG_RETURN_IF_ERROR(deduceExprType(expr)); + NG_RETURN_IF_ERROR(deduceProps(expr, exprProps_)); + const auto &cols = inputCols(); + auto &name = expr->prop(); + auto eq = [&](const ColDef &col) { return col.name == name; }; + auto iter = std::find_if(cols.cbegin(), cols.cend(), eq); + size_t colIdx = std::distance(cols.cbegin(), iter); + colOrderTypes_.emplace_back(std::make_pair(colIdx, factor->orderType())); + } else if (factor->expr()->kind() == Expression::Kind::kVarProperty) { + auto expr = static_cast(factor->expr()); + NG_RETURN_IF_ERROR(deduceExprType(expr)); + NG_RETURN_IF_ERROR(deduceProps(expr, exprProps_)); + const auto &cols = vctx_->getVar(expr->sym()); + auto &name = expr->prop(); + auto eq = [&](const ColDef &col) { return col.name == name; }; + auto iter = std::find_if(cols.cbegin(), cols.cend(), eq); + size_t colIdx = std::distance(cols.cbegin(), iter); + colOrderTypes_.emplace_back(std::make_pair(colIdx, factor->orderType())); + } else { return Status::SemanticError("Order by with invalid expression `%s'", factor->expr()->toString().c_str()); } - auto expr = static_cast(factor->expr()); - NG_RETURN_IF_ERROR(deduceExprType(expr)); - auto &name = expr->prop(); - auto eq = [&](const ColDef &col) { return col.name == name; }; - auto iter = std::find_if(outputs_.cbegin(), outputs_.cend(), eq); - size_t colIdx = std::distance(outputs_.cbegin(), iter); - colOrderTypes_.emplace_back(std::make_pair(colIdx, factor->orderType())); + } + + if (!exprProps_.inputProps().empty() && !exprProps_.varProps().empty()) { + return Status::SemanticError("Not support both input and variable."); + } else if (!exprProps_.inputProps().empty()) { + outputs_ = inputCols(); + } else if (!exprProps_.varProps().empty()) { + if (!userDefinedVarNameList_.empty()) { + if (userDefinedVarNameList_.size() != 1) { + return Status::SemanticError("Multiple user defined vars are not supported yet."); + } + userDefinedVarName_ = *userDefinedVarNameList_.begin(); + outputs_ = vctx_->getVar(userDefinedVarName_); + } } return Status::OK(); @@ -47,6 +66,10 @@ Status OrderByValidator::toPlan() { colNames.emplace_back(col.name); } sortNode->setColNames(std::move(colNames)); + if (!userDefinedVarName_.empty()) { + sortNode->setInputVar(userDefinedVarName_); + } + root_ = sortNode; tail_ = root_; return Status::OK(); diff --git a/src/graph/validator/OrderByValidator.h b/src/graph/validator/OrderByValidator.h index 41fe4c6cbb6..a7608486452 100644 --- a/src/graph/validator/OrderByValidator.h +++ b/src/graph/validator/OrderByValidator.h @@ -24,6 +24,7 @@ class OrderByValidator final : public Validator { private: std::vector> colOrderTypes_; + std::string userDefinedVarName_; }; } // namespace graph } // namespace nebula diff --git a/src/graph/validator/SequentialValidator.cpp b/src/graph/validator/SequentialValidator.cpp index c054a6ef965..61c12573df7 100644 --- a/src/graph/validator/SequentialValidator.cpp +++ b/src/graph/validator/SequentialValidator.cpp @@ -32,16 +32,6 @@ Status SequentialValidator::validateImpl() { } DCHECK(!sentences.empty()); - auto firstSentence = getFirstSentence(sentences.front()); - switch (firstSentence->kind()) { - case Sentence::Kind::kLimit: - case Sentence::Kind::kOrderBy: - case Sentence::Kind::kGroupBy: - return Status::SyntaxError("Could not start with the statement: %s", - firstSentence->toString().c_str()); - default: - break; - } seqAstCtx_->startNode = StartNode::make(seqAstCtx_->qctx); for (auto* sentence : sentences) { diff --git a/src/parser/parser.yy b/src/parser/parser.yy index 961986b1b49..f7deab4e872 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -2544,7 +2544,6 @@ traverse_sentence | order_by_sentence { $$ = $1; } | fetch_sentence { $$ = $1; } | find_path_sentence { $$ = $1; } - | limit_sentence { $$ = $1; } | yield_sentence { $$ = $1; } | get_subgraph_sentence { $$ = $1; } | delete_vertex_sentence { $$ = $1; } @@ -2557,6 +2556,7 @@ traverse_sentence piped_sentence : traverse_sentence { $$ = $1; } | piped_sentence PIPE traverse_sentence { $$ = new PipedSentence($1, $3); } + | piped_sentence PIPE limit_sentence { $$ = new PipedSentence($1, $3); } ; set_sentence diff --git a/tests/tck/features/fetch/FetchVertices.intVid.feature b/tests/tck/features/fetch/FetchVertices.intVid.feature index 8a6e571a22e..30e092fcf6d 100644 --- a/tests/tck/features/fetch/FetchVertices.intVid.feature +++ b/tests/tck/features/fetch/FetchVertices.intVid.feature @@ -39,7 +39,7 @@ Feature: Fetch Int Vid Vertices """ $var = GO FROM hash('Boris Diaw') over like YIELD like._dst as id; FETCH PROP ON player $var.id YIELD player.name as name, player.age | - ORDER BY name + ORDER BY $-.name """ Then the result should be, in order, and the columns 0 should be hashed: | VertexID | name | player.age | diff --git a/tests/tck/features/fetch/FetchVertices.strVid.feature b/tests/tck/features/fetch/FetchVertices.strVid.feature index 9af1bc4e582..4dee9e65a1d 100644 --- a/tests/tck/features/fetch/FetchVertices.strVid.feature +++ b/tests/tck/features/fetch/FetchVertices.strVid.feature @@ -47,7 +47,7 @@ Feature: Fetch String Vertices """ $var = GO FROM 'Boris Diaw' over like YIELD like._dst as id; FETCH PROP ON player $var.id YIELD player.name as name, player.age | - ORDER BY name + ORDER BY $-.name """ Then the result should be, in order: | VertexID | name | player.age | diff --git a/tests/tck/features/go/GroupbyLimit.feature b/tests/tck/features/go/GroupbyLimit.feature index 8e1c0b52684..7fdc010599a 100644 --- a/tests/tck/features/go/GroupbyLimit.feature +++ b/tests/tck/features/go/GroupbyLimit.feature @@ -212,6 +212,11 @@ Feature: Groupby & limit Sentence | "Grizzlies" | 34 | | "Raptors" | 34 | | "Lakers" | 40 | + When executing query: + """ + GROUP BY 1 YIELD 1 + """ + Then a SemanticError should be raised at runtime: Scenario: Groupby with all agg functions When executing query: @@ -365,3 +370,10 @@ Feature: Groupby & limit Sentence | GROUP BY $-.name YIELD $-.name AS name """ Then a SemanticError should be raised at runtime: + + Scenario: Dangle limit + When executing query: + """ + YIELD 1; LIMIT 1; + """ + Then a SyntaxError should be raised at runtime: diff --git a/tests/tck/features/go/Orderby.feature b/tests/tck/features/go/Orderby.feature index f31f53293fb..dee1730e2b8 100644 --- a/tests/tck/features/go/Orderby.feature +++ b/tests/tck/features/go/Orderby.feature @@ -7,7 +7,7 @@ Feature: Orderby Sentence Background: Prepare space Given a graph with space named "nba" - Scenario: Syntax Error + Scenario: Syntax Error or Semantic Error When executing query: """ ORDER BY @@ -22,7 +22,12 @@ Feature: Orderby Sentence """ ORDER BY $-.xx """ - Then a SyntaxError should be raised at runtime: + Then a SemanticError should be raised at runtime: `$-.xx', not exist prop `xx' + When executing query: + """ + ORDER BY 1 + """ + Then a SemanticError should be raised at runtime: Order by with invalid expression `1' Scenario: Empty Input When executing query: @@ -165,6 +170,41 @@ Feature: Orderby Sentence | "Spurs" | | "Hornets" | + Scenario: Order by with Variable + When executing query: + """ + $var = GO FROM "Tony Parker" OVER like YIELD like._dst AS dst; ORDER BY $var.dst DESC + """ + Then the result should be, in order, with relax comparison: + | dst | + | "Tim Duncan" | + | "Manu Ginobili" | + | "LaMarcus Aldridge" | + When executing query: + """ + $var = GO FROM "Tony Parker" OVER like YIELD like._dst AS dst, like.likeness AS likeness; ORDER BY $var.dst DESC, $var.likeness + """ + Then the result should be, in order, with relax comparison: + | dst | likeness | + | "Tim Duncan" | 95 | + | "Manu Ginobili" | 95 | + | "LaMarcus Aldridge" | 90 | + When executing query: + """ + $var = GO FROM "Tony Parker" OVER like YIELD like._dst AS dst; ORDER BY $var.dst DESC | FETCH PROP ON * $-.dst + """ + Then the result should be, in order, with relax comparison: + | vertices_ | + | ("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"}) | + | ("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) | + | ("LaMarcus Aldridge" :player{age: 33, name: "LaMarcus Aldridge"}) | + When executing query: + """ + $var = GO FROM "Tony Parker" OVER like YIELD like._dst AS dst; + GO FROM $var.dst OVER like YIELD like._dst AS id | ORDER BY $var.dst, $-.id; + """ + Then a SemanticError should be raised at runtime: Not support both input and variable. + Scenario: Duplicate columns When executing query: """ diff --git a/tests/tck/features/lookup/ByIndex.feature b/tests/tck/features/lookup/ByIndex.feature index 3c152fcc8d1..e18eb61866b 100644 --- a/tests/tck/features/lookup/ByIndex.feature +++ b/tests/tck/features/lookup/ByIndex.feature @@ -518,7 +518,7 @@ Feature: Lookup by index itself When executing query: """ LOOKUP ON player WHERE player.age < 40 - YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10 + YIELD player.age AS Age, player.name AS Name | order by $-.Age DESC, $-.Name| limit 10 """ Then the result should be, in order, with relax comparison: | VertexID | Age | Name | @@ -535,7 +535,7 @@ Feature: Lookup by index itself When executing query: """ LOOKUP ON player WHERE player.age <= 40 - YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10 + YIELD player.age AS Age, player.name AS Name | order by $-.Age DESC, $-.Name| limit 10 """ Then the result should be, in order, with relax comparison: | VertexID | Age | Name | diff --git a/tests/tck/features/lookup/ByIndex.intVid.feature b/tests/tck/features/lookup/ByIndex.intVid.feature index 6e9d7d7f667..cc1ee530782 100644 --- a/tests/tck/features/lookup/ByIndex.intVid.feature +++ b/tests/tck/features/lookup/ByIndex.intVid.feature @@ -518,7 +518,7 @@ Feature: Lookup by index itself in integer vid When executing query: """ LOOKUP ON player WHERE player.age < 40 - YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10 + YIELD player.age AS Age, player.name AS Name | order by $-.Age DESC, $-.Name| limit 10 """ Then the result should be, in order, with relax comparison, and the columns 0 should be hashed: | VertexID | Age | Name | @@ -535,7 +535,7 @@ Feature: Lookup by index itself in integer vid When executing query: """ LOOKUP ON player WHERE player.age <= 40 - YIELD player.age AS Age, player.name AS Name | order by Age DESC, Name| limit 10 + YIELD player.age AS Age, player.name AS Name | order by $-.Age DESC, $-.Name| limit 10 """ Then the result should be, in order, with relax comparison, and the columns 0 should be hashed: | VertexID | Age | Name | diff --git a/tests/tck/features/optimizer/TopNRule.feature b/tests/tck/features/optimizer/TopNRule.feature index f040b79a220..ad2140e0f51 100644 --- a/tests/tck/features/optimizer/TopNRule.feature +++ b/tests/tck/features/optimizer/TopNRule.feature @@ -12,7 +12,7 @@ Feature: TopN rule """ GO 1 STEPS FROM "Marco Belinelli" OVER like YIELD like.likeness AS likeness | - ORDER BY likeness | + ORDER BY $-.likeness | LIMIT 2 """ Then the result should be, in order: @@ -32,7 +32,7 @@ Feature: TopN rule """ GO 1 STEPS FROM "Marco Belinelli" OVER like REVERSELY YIELD like.likeness AS likeness | - ORDER BY likeness | + ORDER BY $-.likeness | LIMIT 1 """ Then the result should be, in order: @@ -51,7 +51,7 @@ Feature: TopN rule """ GO 1 STEPS FROM "Marco Belinelli" OVER like YIELD like.likeness as likeness | - ORDER BY likeness | + ORDER BY $-.likeness | LIMIT 2, 3 """ Then the result should be, in order: @@ -71,7 +71,7 @@ Feature: TopN rule """ GO 1 STEPS FROM "Marco Belinelli" OVER like YIELD like.likeness AS likeness | - ORDER BY likeness + ORDER BY $-.likeness """ Then the result should be, in any order: | likeness |