summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2017-09-27 17:39:31 -0400
committerDavid Storch <david.storch@10gen.com>2017-09-29 12:15:08 -0400
commiteeb0fa45854de25cd57368585f6b4db10c34ce30 (patch)
treeaf588e4c4ea3155ee305984f0eefda88d3b4eed9 /src
parent0385e6b9514f7856cfbcd4f850930ebbd0895021 (diff)
downloadmongo-eeb0fa45854de25cd57368585f6b4db10c34ce30.tar.gz
SERVER-30582 Permit 'local' readConcern for aggregation explain.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp9
-rw-r--r--src/mongo/db/pipeline/aggregation_request.cpp7
-rw-r--r--src/mongo/db/pipeline/aggregation_request_test.cpp20
-rw-r--r--src/mongo/s/commands/cluster_aggregate.cpp4
-rw-r--r--src/mongo/shell/session.js7
5 files changed, 26 insertions, 21 deletions
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp
index 1077d65a0d2..2ad882ef2f5 100644
--- a/src/mongo/db/commands/run_aggregate.cpp
+++ b/src/mongo/db/commands/run_aggregate.cpp
@@ -57,6 +57,7 @@
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/repl/oplog.h"
+#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/db/views/view.h"
@@ -297,6 +298,14 @@ Status runAggregate(OperationContext* opCtx,
// For operations on views, this will be the underlying namespace.
NamespaceString nss = request.getNamespaceString();
+ if (request.getExplain() &&
+ repl::ReadConcernArgs::get(opCtx).getLevel() != repl::ReadConcernLevel::kLocalReadConcern) {
+ return {ErrorCodes::InvalidOptions,
+ str::stream() << "Explain for the aggregate command "
+ "does not support non-local "
+ "readConcern levels"};
+ }
+
// Parse the user-specified collation, if any.
std::unique_ptr<CollatorInterface> userSpecifiedCollator = request.getCollation().isEmpty()
? nullptr
diff --git a/src/mongo/db/pipeline/aggregation_request.cpp b/src/mongo/db/pipeline/aggregation_request.cpp
index 7c0e6401cd2..88bb2352a60 100644
--- a/src/mongo/db/pipeline/aggregation_request.cpp
+++ b/src/mongo/db/pipeline/aggregation_request.cpp
@@ -254,13 +254,6 @@ StatusWith<AggregationRequest> AggregationRequest::parseFromBSON(
<< "' option is required, except for aggregate with the explain argument"};
}
- if (request.getExplain() && !request.getReadConcern().isEmpty()) {
- return {ErrorCodes::FailedToParse,
- str::stream() << "Aggregation explain does not support the '"
- << repl::ReadConcernArgs::kReadConcernFieldName
- << "' option"};
- }
-
if (request.getExplain() && cmdObj[WriteConcernOptions::kWriteConcernField]) {
return {ErrorCodes::FailedToParse,
str::stream() << "Aggregation explain does not support the'"
diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp
index 312e8158121..112d1d3fb17 100644
--- a/src/mongo/db/pipeline/aggregation_request_test.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_test.cpp
@@ -126,6 +126,19 @@ TEST(AggregationRequestTest, ShouldParseWithSeparateQueryPlannerExplainModeArgAn
ASSERT_EQ(request.getBatchSize(), 10);
}
+TEST(AggregationRequestTest, ShouldParseExplainFlagWithReadConcern) {
+ NamespaceString nss("a.collection");
+ // Non-local readConcern should not be allowed with the explain flag, but this is checked
+ // elsewhere to avoid having to parse the readConcern in AggregationRequest.
+ const BSONObj inputBson =
+ fromjson("{pipeline: [], explain: true, readConcern: {level: 'majority'}}");
+ auto request = unittest::assertGet(AggregationRequest::parseFromBSON(nss, inputBson));
+ ASSERT_TRUE(request.getExplain());
+ ASSERT_BSONOBJ_EQ(request.getReadConcern(),
+ BSON("level"
+ << "majority"));
+}
+
//
// Serialization
//
@@ -399,13 +412,6 @@ TEST(AggregationRequestTest, ShouldRejectExplainFalseWithSeparateExplainArg) {
.getStatus());
}
-TEST(AggregationRequestTest, ShouldRejectExplainWithReadConcernMajority) {
- NamespaceString nss("a.collection");
- const BSONObj inputBson =
- fromjson("{pipeline: [], explain: true, readConcern: {level: 'majority'}}");
- ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
-}
-
TEST(AggregationRequestTest, ShouldRejectExplainExecStatsVerbosityWithReadConcernMajority) {
NamespaceString nss("a.collection");
const BSONObj inputBson = fromjson("{pipeline: [], readConcern: {level: 'majority'}}");
diff --git a/src/mongo/s/commands/cluster_aggregate.cpp b/src/mongo/s/commands/cluster_aggregate.cpp
index a70227b99a4..864e9d457ac 100644
--- a/src/mongo/s/commands/cluster_aggregate.cpp
+++ b/src/mongo/s/commands/cluster_aggregate.cpp
@@ -80,6 +80,10 @@ Document wrapAggAsExplain(Document aggregateCommand, ExplainOptions::Verbosity v
explainCommandBuilder[QueryRequest::kUnwrappedReadPrefField] =
Value(aggregateCommand[QueryRequest::kUnwrappedReadPrefField]);
+ // readConcern needs to be promoted to the top-level of the request.
+ explainCommandBuilder[repl::ReadConcernArgs::kReadConcernFieldName] =
+ Value(aggregateCommand[repl::ReadConcernArgs::kReadConcernFieldName]);
+
// Add explain command options.
for (auto&& explainOption : ExplainOptions::toBSON(verbosity)) {
explainCommandBuilder[explainOption.fieldNameStringData()] = Value(explainOption);
diff --git a/src/mongo/shell/session.js b/src/mongo/shell/session.js
index 7db8f47fbc2..aa1d56afb01 100644
--- a/src/mongo/shell/session.js
+++ b/src/mongo/shell/session.js
@@ -132,13 +132,6 @@ var {
return false;
}
- if (cmdName === "aggregate" && cmdObjUnwrapped.explain) {
- // TODO SERVER-30582: Aggregation's explain doesn't support the "readConcern"
- // option. Note that an aggregation with a $out stage as its last stage still
- // supports a read concern level of "local".
- return false;
- }
-
if (cmdName === "explain") {
return kCommandsThatSupportReadConcern.has(Object.keys(cmdObjUnwrapped.explain)[0]);
}