diff options
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/run_aggregate.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_context.h | 1 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_test.cpp | 88 |
4 files changed, 50 insertions, 48 deletions
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp index 553f956cda6..43d30f873be 100644 --- a/src/mongo/db/commands/run_aggregate.cpp +++ b/src/mongo/db/commands/run_aggregate.cpp @@ -59,6 +59,7 @@ #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/read_concern_args.h" #include "mongo/db/service_context.h" +#include "mongo/db/session_catalog.h" #include "mongo/db/storage/storage_options.h" #include "mongo/db/views/view.h" #include "mongo/db/views/view_catalog.h" @@ -452,6 +453,9 @@ Status runAggregate(OperationContext* opCtx, std::make_shared<PipelineD::MongoDInterface>(opCtx), uassertStatusOK(resolveInvolvedNamespaces(opCtx, request)))); expCtx->tempDir = storageGlobalParams.dbpath + "/_tmp"; + auto session = OperationContextSession::get(opCtx); + expCtx->inSnapshotReadOrMultiDocumentTransaction = + session && session->inSnapshotReadOrMultiDocumentTransaction(); auto pipeline = uassertStatusOK(Pipeline::parse(request.getPipeline(), expCtx)); diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index 9a37f462fe8..6847d43e8a4 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -175,6 +175,7 @@ public: bool inMongos = false; bool allowDiskUse = false; bool bypassDocumentValidation = false; + bool inSnapshotReadOrMultiDocumentTransaction = false; NamespaceString ns; boost::optional<UUID> uuid; diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp index fafcd0d910f..2f6fce9e526 100644 --- a/src/mongo/db/pipeline/pipeline.cpp +++ b/src/mongo/db/pipeline/pipeline.cpp @@ -200,9 +200,6 @@ void Pipeline::validateFacetPipeline() const { } void Pipeline::validateCommon() const { - // TODO SERVER-33551: Don't use presence of WUOW to decide whether we are in a snapshot read or - // multi-doc transaction. - const bool isSnapshotReadOrTxn = static_cast<bool>(pCtx->opCtx->getWriteUnitOfWork()); size_t i = 0; for (auto&& stage : _sources) { auto constraints = stage->constraints(_splitState); @@ -231,7 +228,7 @@ void Pipeline::validateCommon() const { str::stream() << stage->getSourceName() << " can only be run on mongoS", !(constraints.hostRequirement == HostTypeRequirement::kMongoS && !pCtx->inMongos)); - if (isSnapshotReadOrTxn) { + if (pCtx->inSnapshotReadOrMultiDocumentTransaction) { uassert(50742, str::stream() << "Stage not supported with readConcern level \"snapshot\" " "or inside of a multi-document transaction: " diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 19df0485811..23497f83e41 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -1088,20 +1088,20 @@ TEST(PipelineOptimizationTest, // optimizations, but it currently does not. TEST(PipelineOptimizationTest, MatchOnArrayIndexShouldNotSwapSinceCategoryIsArrayMatching) { string inputPipe = R"( - [{$project: {_id: true, a: '$b'}}, - {$match: {a: {$_internalSchemaMatchArrayIndex: + [{$project: {_id: true, a: '$b'}}, + {$match: {a: {$_internalSchemaMatchArrayIndex: {index: 0, namePlaceholder: 'i', expression: {i: {$lt: 0}}}}}}])"; assertPipelineOptimizesTo(inputPipe, inputPipe); inputPipe = R"( - [{$project: {redacted: false}}, - {$match: {a: {$_internalSchemaMatchArrayIndex: + [{$project: {redacted: false}}, + {$match: {a: {$_internalSchemaMatchArrayIndex: {index: 0, namePlaceholder: 'i', expression: {i: {$lt: 0}}}}}}])"; assertPipelineOptimizesTo(inputPipe, inputPipe); inputPipe = R"( - [{$addFields : {a : {$const: 1}}}, - {$match: {a: {$_internalSchemaMatchArrayIndex: + [{$addFields : {a : {$const: 1}}}, + {$match: {a: {$_internalSchemaMatchArrayIndex: {index: 0, namePlaceholder: 'i', expression: {i: {$lt: 0}}}}}}])"; assertPipelineOptimizesTo(inputPipe, inputPipe); } @@ -1207,79 +1207,79 @@ TEST(PipelineOptimizationTest, MatchOnMaxPropertiesShouldNotSwapSinceCategoryIsO // optimizations, but it currently does not. TEST(PipelineOptimizationTest, MatchOnAllowedPropertiesShouldNotSwapSinceCategoryIsOther) { string inputPipe = R"( - [{$project: {_id: true, a: '$b'}}, + [{$project: {_id: true, a: '$b'}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: 1} }}}])"; string outputPipe = R"( - [{$project: {_id: true, a: '$b'}}, + [{$project: {_id: true, a: '$b'}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: {$eq : 1}} }}}])"; string serializedPipe = R"( - [{$project: {_id: true, a: '$b'}}, + [{$project: {_id: true, a: '$b'}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i : 1}} }}])"; assertPipelineOptimizesAndSerializesTo(inputPipe, outputPipe, serializedPipe); inputPipe = R"( - [{$project: {redacted: false}}, + [{$project: {redacted: false}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: 1} }}}])"; outputPipe = R"( - [{$project: {redacted: false}}, + [{$project: {redacted: false}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: {$eq: 1} }}}}])"; serializedPipe = R"( - [{$project: {redacted: false}}, + [{$project: {redacted: false}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: 1} }}}])"; assertPipelineOptimizesAndSerializesTo(inputPipe, outputPipe, serializedPipe); inputPipe = R"( - [{$addFields : {a : {$const: 1}}}, + [{$addFields : {a : {$const: 1}}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: 1} }}}])"; outputPipe = R"( - [{$addFields: {a: {$const: 1}}}, + [{$addFields: {a: {$const: 1}}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ["b"], - namePlaceholder: "i", - patternProperties: [], + properties: ["b"], + namePlaceholder: "i", + patternProperties: [], otherwise: {i: {$eq: 1} }}}}])"; serializedPipe = R"( - [{$addFields : {a : {$const: 1}}}, + [{$addFields : {a : {$const: 1}}}, {$match: {$_internalSchemaAllowedProperties: { - properties: ['b'], - namePlaceholder: 'i', - patternProperties: [], + properties: ['b'], + namePlaceholder: 'i', + patternProperties: [], otherwise: {i: 1} }}}])"; assertPipelineOptimizesAndSerializesTo(inputPipe, outputPipe, serializedPipe); @@ -2463,7 +2463,7 @@ TEST_F(PipelineValidateTest, TopLevelPipelineValidatedForStagesIllegalWithSnapsh auto&& readConcernArgs = repl::ReadConcernArgs::get(ctx->opCtx); ASSERT_OK(readConcernArgs.initialize(readConcernSnapshot["readConcern"])); ASSERT(readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern); - ctx->opCtx->setWriteUnitOfWork(stdx::make_unique<WriteUnitOfWork>(ctx->opCtx)); + ctx->inSnapshotReadOrMultiDocumentTransaction = true; // Make a pipeline with a legal $match, and then an illegal mock stage, and verify that pipeline // creation fails with the expected error code. @@ -2481,7 +2481,7 @@ TEST_F(PipelineValidateTest, FacetPipelineValidatedForStagesIllegalWithSnapshotR auto&& readConcernArgs = repl::ReadConcernArgs::get(ctx->opCtx); ASSERT_OK(readConcernArgs.initialize(readConcernSnapshot["readConcern"])); ASSERT(readConcernArgs.getLevel() == repl::ReadConcernLevel::kSnapshotReadConcern); - ctx->opCtx->setWriteUnitOfWork(stdx::make_unique<WriteUnitOfWork>(ctx->opCtx)); + ctx->inSnapshotReadOrMultiDocumentTransaction = true; // Make a pipeline with a legal $match, and then an illegal mock stage, and verify that pipeline // creation fails with the expected error code. |