summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarmen Liang <karmenliang@gmail.com>2020-07-15 23:33:51 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-20 18:56:48 +0000
commit6551e85a0fa3cc85407e8d46ce8c188247d60211 (patch)
tree518c2c6a4eb75fecb4485cd39ee6b7515af1ece0
parentd0e0220787fa127e0fae9d0c9f691316bd1eb6db (diff)
downloadmongo-6551e85a0fa3cc85407e8d46ce8c188247d60211.tar.gz
SERVER-48827 Implement limit in grammar
-rw-r--r--src/mongo/db/cst/bson_lexer.cpp1
-rw-r--r--src/mongo/db/cst/cst_pipeline_translation.cpp12
-rw-r--r--src/mongo/db/cst/cst_pipeline_translation_test.cpp40
-rw-r--r--src/mongo/db/cst/cst_test.cpp59
-rw-r--r--src/mongo/db/cst/key_fieldname.h4
-rw-r--r--src/mongo/db/cst/pipeline_grammar.yy10
-rw-r--r--src/mongo/db/cst/pipeline_parser_gen.cpp239
-rw-r--r--src/mongo/db/cst/pipeline_parser_gen.hpp169
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