diff options
author | Karmen Liang <karmenliang@gmail.com> | 2020-07-15 23:33:51 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-20 18:56:48 +0000 |
commit | 6551e85a0fa3cc85407e8d46ce8c188247d60211 (patch) | |
tree | 518c2c6a4eb75fecb4485cd39ee6b7515af1ece0 | |
parent | d0e0220787fa127e0fae9d0c9f691316bd1eb6db (diff) | |
download | mongo-6551e85a0fa3cc85407e8d46ce8c188247d60211.tar.gz |
SERVER-48827 Implement limit in grammar
-rw-r--r-- | src/mongo/db/cst/bson_lexer.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/cst/cst_pipeline_translation.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/cst/cst_pipeline_translation_test.cpp | 40 | ||||
-rw-r--r-- | src/mongo/db/cst/cst_test.cpp | 59 | ||||
-rw-r--r-- | src/mongo/db/cst/key_fieldname.h | 4 | ||||
-rw-r--r-- | src/mongo/db/cst/pipeline_grammar.yy | 10 | ||||
-rw-r--r-- | src/mongo/db/cst/pipeline_parser_gen.cpp | 239 | ||||
-rw-r--r-- | src/mongo/db/cst/pipeline_parser_gen.hpp | 169 |
8 files changed, 348 insertions, 186 deletions
diff --git a/src/mongo/db/cst/bson_lexer.cpp b/src/mongo/db/cst/bson_lexer.cpp index d1766c780e1..047f8ef4c95 100644 --- a/src/mongo/db/cst/bson_lexer.cpp +++ b/src/mongo/db/cst/bson_lexer.cpp @@ -45,6 +45,7 @@ const StringMap<PipelineParserGen::token_type> reservedKeyLookup = { {"coll", PipelineParserGen::token::COLL_ARG}, {"pipeline", PipelineParserGen::token::PIPELINE_ARG}, {"$skip", PipelineParserGen::token::STAGE_SKIP}, + {"$limit", PipelineParserGen::token::STAGE_LIMIT}, }; bool isCompound(PipelineParserGen::symbol_type token) { return token.type_get() == static_cast<int>(PipelineParserGen::token::START_OBJECT) || diff --git a/src/mongo/db/cst/cst_pipeline_translation.cpp b/src/mongo/db/cst/cst_pipeline_translation.cpp index 4b39ef388a7..5afcf8e70fd 100644 --- a/src/mongo/db/cst/cst_pipeline_translation.cpp +++ b/src/mongo/db/cst/cst_pipeline_translation.cpp @@ -38,6 +38,7 @@ #include "mongo/db/cst/key_value.h" #include "mongo/db/exec/inclusion_projection_executor.h" #include "mongo/db/pipeline/document_source.h" +#include "mongo/db/pipeline/document_source_limit.h" #include "mongo/db/pipeline/document_source_project.h" #include "mongo/db/pipeline/document_source_skip.h" #include "mongo/db/pipeline/expression_context.h" @@ -45,6 +46,7 @@ #include "mongo/db/query/projection_ast.h" #include "mongo/db/query/projection_parser.h" #include "mongo/util/intrusive_counter.h" +#include "mongo/util/visit_helper.h" namespace mongo::cst_pipeline_translation { namespace { @@ -107,6 +109,14 @@ auto translateSkip(const CNode& cst, const boost::intrusive_ptr<ExpressionContex } /** + * Unwrap a limit stage CNode and produce a DocumentSourceLimit. + */ +auto translateLimit(const CNode& cst, const boost::intrusive_ptr<ExpressionContext>& expCtx) { + UserLong limit = translateNumToLong(cst); + return DocumentSourceLimit::create(expCtx, limit); +} + +/** * Walk an aggregation pipeline stage object CNode and produce a DocumentSource. */ boost::intrusive_ptr<DocumentSource> translateSource( @@ -116,6 +126,8 @@ boost::intrusive_ptr<DocumentSource> translateSource( return translateProject(cst.objectChildren()[0].second, expCtx); case KeyFieldname::skip: return translateSkip(cst.objectChildren()[0].second, expCtx); + case KeyFieldname::limit: + return translateLimit(cst.objectChildren()[0].second, expCtx); default: MONGO_UNREACHABLE; } diff --git a/src/mongo/db/cst/cst_pipeline_translation_test.cpp b/src/mongo/db/cst/cst_pipeline_translation_test.cpp index 90152227f91..6a7760b1bab 100644 --- a/src/mongo/db/cst/cst_pipeline_translation_test.cpp +++ b/src/mongo/db/cst/cst_pipeline_translation_test.cpp @@ -41,6 +41,7 @@ #include "mongo/db/cst/key_value.h" #include "mongo/db/exec/document_value/document.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/pipeline/document_source_limit.h" #include "mongo/db/pipeline/document_source_single_document_transformation.h" #include "mongo/db/pipeline/document_source_skip.h" #include "mongo/db/pipeline/expression_context_for_test.h" @@ -206,5 +207,44 @@ TEST(CstTest, TranslatesSkipWithLong) { ASSERT_EQ((dynamic_cast<DocumentSourceSkip&>(**iter).getSkip()), 8223372036854775807); } +TEST(CstTest, TranslatesLimitWithInt) { + auto nss = NamespaceString{"db", "coll"}; + const auto cst = CNode{CNode::ArrayChildren{ + CNode{CNode::ObjectChildren{{KeyFieldname::limit, CNode{UserInt{10}}}}}}}; + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest(nss)); + auto pipeline = cst_pipeline_translation::translatePipeline(cst, expCtx); + auto& sources = pipeline->getSources(); + ASSERT_EQ(1u, sources.size()); + auto iter = sources.begin(); + ASSERT(typeid(DocumentSourceLimit) == typeid(**iter)); + ASSERT_EQ(10ll, dynamic_cast<DocumentSourceLimit&>(**iter).getLimit()); +} + +TEST(CstTest, TranslatesLimitWithDouble) { + auto nss = NamespaceString{"db", "coll"}; + const auto cst = CNode{CNode::ArrayChildren{ + CNode{CNode::ObjectChildren{{KeyFieldname::limit, CNode{UserDouble{10.5}}}}}}}; + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest(nss)); + auto pipeline = cst_pipeline_translation::translatePipeline(cst, expCtx); + auto& sources = pipeline->getSources(); + ASSERT_EQ(1u, sources.size()); + auto iter = sources.begin(); + ASSERT(typeid(DocumentSourceLimit) == typeid(**iter)); + ASSERT_EQ(10ll, dynamic_cast<DocumentSourceLimit&>(**iter).getLimit()); +} + +TEST(CstTest, TranslatesLimitWithLong) { + auto nss = NamespaceString{"db", "coll"}; + const auto cst = CNode{CNode::ArrayChildren{ + CNode{CNode::ObjectChildren{{KeyFieldname::limit, CNode{UserLong{123123123123}}}}}}}; + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest(nss)); + auto pipeline = cst_pipeline_translation::translatePipeline(cst, expCtx); + auto& sources = pipeline->getSources(); + ASSERT_EQ(1u, sources.size()); + auto iter = sources.begin(); + ASSERT(typeid(DocumentSourceLimit) == typeid(**iter)); + ASSERT_EQ(123123123123, dynamic_cast<DocumentSourceLimit&>(**iter).getLimit()); +} + } // namespace } // namespace mongo diff --git a/src/mongo/db/cst/cst_test.cpp b/src/mongo/db/cst/cst_test.cpp index 97dbf6ebc0c..4ed9b889f15 100644 --- a/src/mongo/db/cst/cst_test.cpp +++ b/src/mongo/db/cst/cst_test.cpp @@ -198,5 +198,64 @@ TEST(CstGrammarTest, InvalidParseSkipString) { ASSERT_THROWS_CODE(parseTree.parse(), AssertionException, ErrorCodes::FailedToParse); } +TEST(CstGrammarTest, ParsesLimitInt) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: 5}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_EQ(0, parseTree.parse()); + auto stages = stdx::get<CNode::ArrayChildren>(output.payload); + ASSERT_EQ(1, stages.size()); + ASSERT(KeyFieldname::limit == stages[0].firstKeyFieldname()); + ASSERT_BSONOBJ_EQ(fromjson("{limit : \"<UserInt 5>\"}"), stages[0].toBson()); +} + +TEST(CstGrammarTest, ParsesLimitDouble) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: 5.0}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_EQ(0, parseTree.parse()); + auto stages = stdx::get<CNode::ArrayChildren>(output.payload); + ASSERT_EQ(1, stages.size()); + ASSERT(KeyFieldname::limit == stages[0].firstKeyFieldname()); + ASSERT_BSONOBJ_EQ(fromjson("{limit : \"<UserDouble 5.000000>\"}"), stages[0].toBson()); +} + +TEST(CstGrammarTest, ParsesLimitLong) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: 123123123123}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_EQ(0, parseTree.parse()); + auto stages = stdx::get<CNode::ArrayChildren>(output.payload); + ASSERT_EQ(1, stages.size()); + ASSERT(KeyFieldname::limit == stages[0].firstKeyFieldname()); + ASSERT_BSONOBJ_EQ(fromjson("{limit : \"<UserLong 123123123123>\"}"), stages[0].toBson()); +} + +TEST(CstGrammarTest, InvalidParseLimitString) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: \"5\"}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_THROWS_CODE(parseTree.parse(), AssertionException, ErrorCodes::FailedToParse); +} +TEST(CstGrammarTest, InvalidParseLimitObject) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: {}}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_THROWS_CODE(parseTree.parse(), AssertionException, ErrorCodes::FailedToParse); +} + +TEST(CstGrammarTest, InvalidParseLimitArray) { + CNode output; + auto input = fromjson("{pipeline: [{$limit: [2]}]}"); + BSONLexer lexer(input["pipeline"].Array()); + auto parseTree = PipelineParserGen(lexer, &output); + ASSERT_THROWS_CODE(parseTree.parse(), AssertionException, ErrorCodes::FailedToParse); +} + } // namespace } // namespace mongo diff --git a/src/mongo/db/cst/key_fieldname.h b/src/mongo/db/cst/key_fieldname.h index e6c36bf49be..5659ed15846 100644 --- a/src/mongo/db/cst/key_fieldname.h +++ b/src/mongo/db/cst/key_fieldname.h @@ -41,8 +41,8 @@ ENUMIFY(unionWith) \ ENUMIFY(collArg) \ ENUMIFY(pipelineArg) \ - ENUMIFY(limit) \ - ENUMIFY(skip) + ENUMIFY(skip) \ + ENUMIFY(limit) MAKE_PRINTABLE_ENUM(KeyFieldname, KEYFIELDNAMES); MAKE_PRINTABLE_ENUM_STRING_ARRAY(key_fieldname, KeyFieldname, KEYFIELDNAMES); diff --git a/src/mongo/db/cst/pipeline_grammar.yy b/src/mongo/db/cst/pipeline_grammar.yy index 9d6a1bbe906..824628e3a33 100644 --- a/src/mongo/db/cst/pipeline_grammar.yy +++ b/src/mongo/db/cst/pipeline_grammar.yy @@ -109,6 +109,7 @@ STAGE_INHIBIT_OPTIMIZATION STAGE_UNION_WITH STAGE_SKIP + STAGE_LIMIT // $unionWith arguments. COLL_ARG @@ -126,7 +127,7 @@ // // Semantic values (aka the C++ types produced by the actions). // -%nterm <CNode> stageList stage inhibitOptimization unionWith num skip +%nterm <CNode> stageList stage inhibitOptimization unionWith num skip limit // // Grammar rules @@ -151,7 +152,7 @@ stageList[result]: START_ORDERED_OBJECT: { lexer.sortObjTokens(); } START_OBJECT; stage: - inhibitOptimization | unionWith | skip + inhibitOptimization | unionWith | skip | limit ; inhibitOptimization: @@ -188,4 +189,9 @@ skip: $skip = CNode{CNode::ObjectChildren{std::pair{KeyFieldname::skip, $num}}}; }; +limit: + STAGE_LIMIT num { + $limit = CNode{CNode::ObjectChildren{std::pair{KeyFieldname::limit, $num}}}; +}; + %% diff --git a/src/mongo/db/cst/pipeline_parser_gen.cpp b/src/mongo/db/cst/pipeline_parser_gen.cpp index 159de24c602..1767319051f 100644 --- a/src/mongo/db/cst/pipeline_parser_gen.cpp +++ b/src/mongo/db/cst/pipeline_parser_gen.cpp @@ -204,32 +204,33 @@ PipelineParserGen::stack_symbol_type::stack_symbol_type() {} PipelineParserGen::stack_symbol_type::stack_symbol_type(YY_RVREF(stack_symbol_type) that) : super_type(YY_MOVE(that.state), YY_MOVE(that.location)) { switch (that.kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.YY_MOVE_OR_COPY<CNode>(YY_MOVE(that.value)); break; - case 16: // BOOL + case 17: // BOOL value.YY_MOVE_OR_COPY<bool>(YY_MOVE(that.value)); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.YY_MOVE_OR_COPY<double>(YY_MOVE(that.value)); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.YY_MOVE_OR_COPY<int>(YY_MOVE(that.value)); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.YY_MOVE_OR_COPY<long long>(YY_MOVE(that.value)); break; - case 12: // STRING + case 13: // STRING value.YY_MOVE_OR_COPY<std::string>(YY_MOVE(that.value)); break; @@ -246,32 +247,33 @@ PipelineParserGen::stack_symbol_type::stack_symbol_type(YY_RVREF(stack_symbol_ty PipelineParserGen::stack_symbol_type::stack_symbol_type(state_type s, YY_MOVE_REF(symbol_type) that) : super_type(s, YY_MOVE(that.location)) { switch (that.kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.move<CNode>(YY_MOVE(that.value)); break; - case 16: // BOOL + case 17: // BOOL value.move<bool>(YY_MOVE(that.value)); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.move<double>(YY_MOVE(that.value)); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.move<int>(YY_MOVE(that.value)); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.move<long long>(YY_MOVE(that.value)); break; - case 12: // STRING + case 13: // STRING value.move<std::string>(YY_MOVE(that.value)); break; @@ -288,32 +290,33 @@ PipelineParserGen::stack_symbol_type& PipelineParserGen::stack_symbol_type::oper const stack_symbol_type& that) { state = that.state; switch (that.kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.copy<CNode>(that.value); break; - case 16: // BOOL + case 17: // BOOL value.copy<bool>(that.value); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.copy<double>(that.value); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.copy<int>(that.value); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.copy<long long>(that.value); break; - case 12: // STRING + case 13: // STRING value.copy<std::string>(that.value); break; @@ -329,32 +332,33 @@ PipelineParserGen::stack_symbol_type& PipelineParserGen::stack_symbol_type::oper stack_symbol_type& that) { state = that.state; switch (that.kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.move<CNode>(that.value); break; - case 16: // BOOL + case 17: // BOOL value.move<bool>(that.value); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.move<double>(that.value); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.move<int>(that.value); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.move<long long>(that.value); break; - case 12: // STRING + case 13: // STRING value.move<std::string>(that.value); break; @@ -581,32 +585,33 @@ int PipelineParserGen::parse() { correct type. The default '$$ = $1' action is NOT applied when using variants. */ switch (yyr1_[yyn]) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit yylhs.value.emplace<CNode>(); break; - case 16: // BOOL + case 17: // BOOL yylhs.value.emplace<bool>(); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE yylhs.value.emplace<double>(); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT yylhs.value.emplace<int>(); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG yylhs.value.emplace<long long>(); break; - case 12: // STRING + case 13: // STRING yylhs.value.emplace<std::string>(); break; @@ -630,72 +635,80 @@ int PipelineParserGen::parse() { { switch (yyn) { case 2: -#line 137 "src/mongo/db/cst/pipeline_grammar.yy" +#line 138 "src/mongo/db/cst/pipeline_grammar.yy" { *cst = std::move(yystack_[1].value.as<CNode>()); } -#line 706 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 711 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 3: -#line 142 "src/mongo/db/cst/pipeline_grammar.yy" +#line 143 "src/mongo/db/cst/pipeline_grammar.yy" { } -#line 712 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 717 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 4: -#line 143 "src/mongo/db/cst/pipeline_grammar.yy" +#line 144 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{CNode::ArrayChildren{yystack_[2].value.as<CNode>()}}; } -#line 720 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 725 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 5: -#line 151 "src/mongo/db/cst/pipeline_grammar.yy" +#line 152 "src/mongo/db/cst/pipeline_grammar.yy" { lexer.sortObjTokens(); } -#line 726 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 731 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 7: -#line 154 "src/mongo/db/cst/pipeline_grammar.yy" +#line 155 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = yystack_[0].value.as<CNode>(); } -#line 732 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 737 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 8: -#line 154 "src/mongo/db/cst/pipeline_grammar.yy" +#line 155 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = yystack_[0].value.as<CNode>(); } -#line 738 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 743 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 9: -#line 154 "src/mongo/db/cst/pipeline_grammar.yy" +#line 155 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = yystack_[0].value.as<CNode>(); } -#line 744 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 749 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; case 10: -#line 158 "src/mongo/db/cst/pipeline_grammar.yy" +#line 155 "src/mongo/db/cst/pipeline_grammar.yy" + { + yylhs.value.as<CNode>() = yystack_[0].value.as<CNode>(); + } +#line 755 "src/mongo/db/cst/pipeline_parser_gen.cpp" + break; + + case 11: +#line 159 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{CNode::ObjectChildren{ std::pair{KeyFieldname::inhibitOptimization, CNode::noopLeaf()}}}; } -#line 753 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 764 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; - case 11: -#line 164 "src/mongo/db/cst/pipeline_grammar.yy" + case 12: +#line 165 "src/mongo/db/cst/pipeline_grammar.yy" { auto coll = CNode{UserString(yystack_[3].value.as<std::string>())}; auto pipeline = CNode{UserDouble(yystack_[1].value.as<double>())}; @@ -705,45 +718,54 @@ int PipelineParserGen::parse() { {KeyFieldname::collArg, std::move(coll)}, {KeyFieldname::pipelineArg, std::move(pipeline)}}}}}}; } -#line 767 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 778 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; - case 12: -#line 175 "src/mongo/db/cst/pipeline_grammar.yy" + case 13: +#line 176 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{UserInt(yystack_[0].value.as<int>())}; } -#line 775 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 786 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; - case 13: -#line 178 "src/mongo/db/cst/pipeline_grammar.yy" + case 14: +#line 179 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{UserLong(yystack_[0].value.as<long long>())}; } -#line 783 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 794 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; - case 14: -#line 181 "src/mongo/db/cst/pipeline_grammar.yy" + case 15: +#line 182 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{UserDouble(yystack_[0].value.as<double>())}; } -#line 791 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 802 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; - case 15: -#line 187 "src/mongo/db/cst/pipeline_grammar.yy" + case 16: +#line 188 "src/mongo/db/cst/pipeline_grammar.yy" { yylhs.value.as<CNode>() = CNode{CNode::ObjectChildren{ std::pair{KeyFieldname::skip, yystack_[0].value.as<CNode>()}}}; } -#line 799 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 810 "src/mongo/db/cst/pipeline_parser_gen.cpp" + break; + + case 17: +#line 193 "src/mongo/db/cst/pipeline_grammar.yy" + { + yylhs.value.as<CNode>() = CNode{CNode::ObjectChildren{ + std::pair{KeyFieldname::limit, yystack_[0].value.as<CNode>()}}}; + } +#line 818 "src/mongo/db/cst/pipeline_parser_gen.cpp" break; -#line 803 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 822 "src/mongo/db/cst/pipeline_parser_gen.cpp" default: break; @@ -912,31 +934,34 @@ const signed char PipelineParserGen::yypact_ninf_ = -11; const signed char PipelineParserGen::yytable_ninf_ = -1; -const signed char PipelineParserGen::yypact_[] = {1, 4, 8, -7, 3, -11, 7, -11, -10, 9, - -11, -11, -11, -11, 10, 2, 12, -11, -11, -11, - -11, 4, -11, -1, -11, -11, 5, 6, 13, -11}; +const signed char PipelineParserGen::yypact_[] = { + 2, 5, 9, -7, 4, -11, 8, -11, -10, -10, 10, -11, -11, -11, -11, -11, 11, + 1, 13, -11, -11, -11, -11, -11, 5, -11, 0, -11, -11, 6, 3, 16, -11}; -const signed char PipelineParserGen::yydefact_[] = { - 0, 3, 0, 0, 0, 1, 0, 5, 0, 0, 7, 8, 9, 2, 0, 0, 0, 12, 13, 14, 15, 3, 10, 0, 6, 4, 0, 0, 0, 11}; +const signed char PipelineParserGen::yydefact_[] = {0, 3, 0, 0, 0, 1, 0, 5, 0, 0, 0, + 7, 8, 9, 10, 2, 0, 0, 0, 13, 14, 15, + 16, 17, 3, 11, 0, 6, 4, 0, 0, 0, 12}; -const signed char PipelineParserGen::yypgoto_[] = {-11, -3, -11, -11, -11, -11, -11, -11, -11, -11}; +const signed char PipelineParserGen::yypgoto_[] = { + -11, -3, -11, -11, -11, 14, -11, -11, -11, -11, -11}; -const signed char PipelineParserGen::yydefgoto_[] = {-1, 4, 9, 10, 11, 20, 12, 2, 15, 16}; +const signed char PipelineParserGen::yydefgoto_[] = {-1, 4, 10, 11, 12, 22, 13, 14, 2, 17, 18}; -const signed char PipelineParserGen::yytable_[] = {6, 7, 8, 17, 18, 19, 1, 3, 5, 13, 14, - 26, 23, 21, 22, 24, 27, 29, 25, 0, 0, 28}; +const signed char PipelineParserGen::yytable_[] = {6, 7, 8, 9, 19, 20, 21, 1, 3, 5, 15, 16, + 26, 29, 24, 25, 27, 0, 30, 31, 32, 28, 0, 23}; -const signed char PipelineParserGen::yycheck_[] = {7, 8, 9, 13, 14, 15, 5, 3, 0, 6, 3, - 12, 10, 4, 4, 3, 11, 4, 21, -1, -1, 15}; +const signed char PipelineParserGen::yycheck_[] = {7, 8, 9, 10, 14, 15, 16, 5, 3, 0, 6, 3, + 11, 13, 4, 4, 3, -1, 12, 16, 4, 24, -1, 9}; -const signed char PipelineParserGen::yystos_[] = {0, 5, 24, 3, 18, 0, 7, 8, 9, 19, - 20, 21, 23, 6, 3, 25, 26, 13, 14, 15, - 22, 4, 4, 10, 3, 18, 12, 11, 15, 4}; +const signed char PipelineParserGen::yystos_[] = {0, 5, 26, 3, 19, 0, 7, 8, 9, 10, 20, + 21, 22, 24, 25, 6, 3, 27, 28, 14, 15, 16, + 23, 23, 4, 4, 11, 3, 19, 13, 12, 16, 4}; const signed char PipelineParserGen::yyr1_[] = { - 0, 17, 24, 18, 18, 26, 25, 19, 19, 19, 20, 21, 22, 22, 22, 23}; + 0, 18, 26, 19, 19, 28, 27, 20, 20, 20, 20, 21, 22, 23, 23, 23, 24, 25}; -const signed char PipelineParserGen::yyr2_[] = {0, 2, 3, 0, 4, 0, 2, 1, 1, 1, 3, 7, 1, 1, 1, 2}; +const signed char PipelineParserGen::yyr2_[] = { + 0, 2, 3, 0, 4, 0, 2, 1, 1, 1, 1, 3, 7, 1, 1, 1, 2, 2}; #if YYDEBUG @@ -952,6 +977,7 @@ const char* const PipelineParserGen::yytname_[] = {"\"EOF\"", "STAGE_INHIBIT_OPTIMIZATION", "STAGE_UNION_WITH", "STAGE_SKIP", + "STAGE_LIMIT", "COLL_ARG", "PIPELINE_ARG", "STRING", @@ -966,6 +992,7 @@ const char* const PipelineParserGen::yytname_[] = {"\"EOF\"", "unionWith", "num", "skip", + "limit", "pipeline", "START_ORDERED_OBJECT", "$@1", @@ -975,7 +1002,7 @@ const char* const PipelineParserGen::yytname_[] = {"\"EOF\"", #if YYDEBUG const unsigned char PipelineParserGen::yyrline_[] = { - 0, 137, 137, 142, 143, 151, 151, 154, 154, 154, 158, 164, 175, 178, 181, 187}; + 0, 138, 138, 143, 144, 152, 152, 155, 155, 155, 155, 159, 165, 176, 179, 182, 188, 193}; void PipelineParserGen::yy_stack_print_() const { *yycdebug_ << "Stack now"; @@ -998,6 +1025,6 @@ void PipelineParserGen::yy_reduce_print_(int yyrule) const { #line 52 "src/mongo/db/cst/pipeline_grammar.yy" } // namespace mongo -#line 1106 "src/mongo/db/cst/pipeline_parser_gen.cpp" +#line 1131 "src/mongo/db/cst/pipeline_parser_gen.cpp" -#line 191 "src/mongo/db/cst/pipeline_grammar.yy" +#line 197 "src/mongo/db/cst/pipeline_grammar.yy" diff --git a/src/mongo/db/cst/pipeline_parser_gen.hpp b/src/mongo/db/cst/pipeline_parser_gen.hpp index 4c1a36754c0..c742e600bca 100644 --- a/src/mongo/db/cst/pipeline_parser_gen.hpp +++ b/src/mongo/db/cst/pipeline_parser_gen.hpp @@ -373,6 +373,7 @@ public: // unionWith // num // skip + // limit char dummy1[sizeof(CNode)]; // BOOL @@ -438,13 +439,14 @@ public: STAGE_INHIBIT_OPTIMIZATION = 7, // STAGE_INHIBIT_OPTIMIZATION STAGE_UNION_WITH = 8, // STAGE_UNION_WITH STAGE_SKIP = 9, // STAGE_SKIP - COLL_ARG = 10, // COLL_ARG - PIPELINE_ARG = 11, // PIPELINE_ARG - STRING = 12, // STRING - NUMBER_INT = 13, // NUMBER_INT - NUMBER_LONG = 14, // NUMBER_LONG - NUMBER_DOUBLE = 15, // NUMBER_DOUBLE - BOOL = 16 // BOOL + STAGE_LIMIT = 10, // STAGE_LIMIT + COLL_ARG = 11, // COLL_ARG + PIPELINE_ARG = 12, // PIPELINE_ARG + STRING = 13, // STRING + NUMBER_INT = 14, // NUMBER_INT + NUMBER_LONG = 15, // NUMBER_LONG + NUMBER_DOUBLE = 16, // NUMBER_DOUBLE + BOOL = 17 // BOOL }; /// Backward compatibility alias (Bison 3.6). typedef token_kind_type yytokentype; @@ -459,7 +461,7 @@ public: /// Symbol kinds. struct symbol_kind { enum symbol_kind_type { - YYNTOKENS = 17, ///< Number of tokens. + YYNTOKENS = 18, ///< Number of tokens. S_YYEMPTY = -2, S_YYEOF = 0, // "EOF" S_YYerror = 1, // error @@ -471,23 +473,25 @@ public: S_STAGE_INHIBIT_OPTIMIZATION = 7, // STAGE_INHIBIT_OPTIMIZATION S_STAGE_UNION_WITH = 8, // STAGE_UNION_WITH S_STAGE_SKIP = 9, // STAGE_SKIP - S_COLL_ARG = 10, // COLL_ARG - S_PIPELINE_ARG = 11, // PIPELINE_ARG - S_STRING = 12, // STRING - S_NUMBER_INT = 13, // NUMBER_INT - S_NUMBER_LONG = 14, // NUMBER_LONG - S_NUMBER_DOUBLE = 15, // NUMBER_DOUBLE - S_BOOL = 16, // BOOL - S_YYACCEPT = 17, // $accept - S_stageList = 18, // stageList - S_stage = 19, // stage - S_inhibitOptimization = 20, // inhibitOptimization - S_unionWith = 21, // unionWith - S_num = 22, // num - S_skip = 23, // skip - S_pipeline = 24, // pipeline - S_START_ORDERED_OBJECT = 25, // START_ORDERED_OBJECT - S_26_1 = 26 // $@1 + S_STAGE_LIMIT = 10, // STAGE_LIMIT + S_COLL_ARG = 11, // COLL_ARG + S_PIPELINE_ARG = 12, // PIPELINE_ARG + S_STRING = 13, // STRING + S_NUMBER_INT = 14, // NUMBER_INT + S_NUMBER_LONG = 15, // NUMBER_LONG + S_NUMBER_DOUBLE = 16, // NUMBER_DOUBLE + S_BOOL = 17, // BOOL + S_YYACCEPT = 18, // $accept + S_stageList = 19, // stageList + S_stage = 20, // stage + S_inhibitOptimization = 21, // inhibitOptimization + S_unionWith = 22, // unionWith + S_num = 23, // num + S_skip = 24, // skip + S_limit = 25, // limit + S_pipeline = 26, // pipeline + S_START_ORDERED_OBJECT = 27, // START_ORDERED_OBJECT + S_28_1 = 28 // $@1 }; }; @@ -516,32 +520,33 @@ public: basic_symbol(basic_symbol&& that) : Base(std::move(that)), value(), location(std::move(that.location)) { switch (this->kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.move<CNode>(std::move(that.value)); break; - case 16: // BOOL + case 17: // BOOL value.move<bool>(std::move(that.value)); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.move<double>(std::move(that.value)); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.move<int>(std::move(that.value)); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.move<long long>(std::move(that.value)); break; - case 12: // STRING + case 13: // STRING value.move<std::string>(std::move(that.value)); break; @@ -622,32 +627,33 @@ public: // Value type destructor. switch (yykind) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.template destroy<CNode>(); break; - case 16: // BOOL + case 17: // BOOL value.template destroy<bool>(); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.template destroy<double>(); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.template destroy<int>(); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.template destroy<long long>(); break; - case 12: // STRING + case 13: // STRING value.template destroy<std::string>(); break; @@ -735,8 +741,8 @@ public: tok == token::START_OBJECT || tok == token::END_OBJECT || tok == token::START_ARRAY || tok == token::END_ARRAY || tok == token::STAGE_INHIBIT_OPTIMIZATION || tok == token::STAGE_UNION_WITH || - tok == token::STAGE_SKIP || tok == token::COLL_ARG || - tok == token::PIPELINE_ARG); + tok == token::STAGE_SKIP || tok == token::STAGE_LIMIT || + tok == token::COLL_ARG || tok == token::PIPELINE_ARG); } #else symbol_type(int tok, const location_type& l) : super_type(token_type(tok), l) { @@ -744,8 +750,8 @@ public: tok == token::START_OBJECT || tok == token::END_OBJECT || tok == token::START_ARRAY || tok == token::END_ARRAY || tok == token::STAGE_INHIBIT_OPTIMIZATION || tok == token::STAGE_UNION_WITH || - tok == token::STAGE_SKIP || tok == token::COLL_ARG || - tok == token::PIPELINE_ARG); + tok == token::STAGE_SKIP || tok == token::STAGE_LIMIT || + tok == token::COLL_ARG || tok == token::PIPELINE_ARG); } #endif #if 201103L <= YY_CPLUSPLUS @@ -938,6 +944,15 @@ public: } #endif #if 201103L <= YY_CPLUSPLUS + static symbol_type make_STAGE_LIMIT(location_type l) { + return symbol_type(token::STAGE_LIMIT, std::move(l)); + } +#else + static symbol_type make_STAGE_LIMIT(const location_type& l) { + return symbol_type(token::STAGE_LIMIT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS static symbol_type make_COLL_ARG(location_type l) { return symbol_type(token::COLL_ARG, std::move(l)); } @@ -1280,8 +1295,8 @@ private: /// Constants. enum { - yylast_ = 21, ///< Last index in yytable_. - yynnts_ = 10, ///< Number of nonterminal symbols. + yylast_ = 23, ///< Last index in yytable_. + yynnts_ = 11, ///< Number of nonterminal symbols. yyfinal_ = 5 ///< Termination state number. }; @@ -1300,32 +1315,33 @@ template <typename Base> PipelineParserGen::basic_symbol<Base>::basic_symbol(const basic_symbol& that) : Base(that), value(), location(that.location) { switch (this->kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.copy<CNode>(YY_MOVE(that.value)); break; - case 16: // BOOL + case 17: // BOOL value.copy<bool>(YY_MOVE(that.value)); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.copy<double>(YY_MOVE(that.value)); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.copy<int>(YY_MOVE(that.value)); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.copy<long long>(YY_MOVE(that.value)); break; - case 12: // STRING + case 13: // STRING value.copy<std::string>(YY_MOVE(that.value)); break; @@ -1350,32 +1366,33 @@ template <typename Base> void PipelineParserGen::basic_symbol<Base>::move(basic_symbol& s) { super_type::move(s); switch (this->kind()) { - case 18: // stageList - case 19: // stage - case 20: // inhibitOptimization - case 21: // unionWith - case 22: // num - case 23: // skip + case 19: // stageList + case 20: // stage + case 21: // inhibitOptimization + case 22: // unionWith + case 23: // num + case 24: // skip + case 25: // limit value.move<CNode>(YY_MOVE(s.value)); break; - case 16: // BOOL + case 17: // BOOL value.move<bool>(YY_MOVE(s.value)); break; - case 15: // NUMBER_DOUBLE + case 16: // NUMBER_DOUBLE value.move<double>(YY_MOVE(s.value)); break; - case 13: // NUMBER_INT + case 14: // NUMBER_INT value.move<int>(YY_MOVE(s.value)); break; - case 14: // NUMBER_LONG + case 15: // NUMBER_LONG value.move<long long>(YY_MOVE(s.value)); break; - case 12: // STRING + case 13: // STRING value.move<std::string>(YY_MOVE(s.value)); break; @@ -1419,7 +1436,7 @@ inline PipelineParserGen::symbol_kind_type PipelineParserGen::by_kind::type_get( #line 52 "src/mongo/db/cst/pipeline_grammar.yy" } // namespace mongo -#line 1705 "src/mongo/db/cst/pipeline_parser_gen.hpp" +#line 1728 "src/mongo/db/cst/pipeline_parser_gen.hpp" #endif // !YY_YY_SRC_MONGO_DB_CST_PIPELINE_PARSER_GEN_HPP_INCLUDED |