summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp4
-rw-r--r--src/mongo/db/pipeline/expression_context.h1
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp5
-rw-r--r--src/mongo/db/pipeline/pipeline_test.cpp88
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.