summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-05-11 17:36:52 -0400
committerMathias Stearn <mathias@10gen.com>2015-05-14 18:59:03 -0400
commit463d3343d559590d60cfd5c48ac98ad675d5390e (patch)
tree5ab045f64656074016c08229ae0bcc6734579e6e /src/mongo/db
parent22de12dd4ac510cd2a37b643eb528673f651e21b (diff)
downloadmongo-463d3343d559590d60cfd5c48ac98ad675d5390e.tar.gz
SERVER-18227 Add bypassDocumentValidation option to commands that need it
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/auth/action_types.txt1
-rw-r--r--src/mongo/db/auth/role_graph_builtin_roles.cpp15
-rw-r--r--src/mongo/db/catalog/document_validation.h9
-rw-r--r--src/mongo/db/commands/clone.cpp9
-rw-r--r--src/mongo/db/commands/clone_collection.cpp8
-rw-r--r--src/mongo/db/commands/copydb.cpp5
-rw-r--r--src/mongo/db/commands/copydb_common.cpp5
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp5
-rw-r--r--src/mongo/db/commands/find_and_modify_common.cpp5
-rw-r--r--src/mongo/db/commands/mr.cpp9
-rw-r--r--src/mongo/db/commands/mr_common.cpp5
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp5
-rw-r--r--src/mongo/db/commands/write_commands/write_commands_common.cpp28
-rw-r--r--src/mongo/db/pipeline/document_source.h7
-rw-r--r--src/mongo/db/pipeline/document_source_out.cpp9
-rw-r--r--src/mongo/db/pipeline/expression_context.h20
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp14
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp18
18 files changed, 139 insertions, 38 deletions
diff --git a/src/mongo/db/auth/action_types.txt b/src/mongo/db/auth/action_types.txt
index 62120c7156e..f6c9164b1e8 100644
--- a/src/mongo/db/auth/action_types.txt
+++ b/src/mongo/db/auth/action_types.txt
@@ -11,6 +11,7 @@
"auditLogRotate", # Not used for permissions checks, but to id the event in logs.
"authCheck", # Not used for permissions checks, but to id the authorization-checking event in logs.
"authenticate", # Not used for permission checks, but to id authentication events in logs.
+"bypassDocumentValidation", # For bypassDocumentValidation command option.
"changeCustomData",
"changePassword",
"changeOwnPassword",
diff --git a/src/mongo/db/auth/role_graph_builtin_roles.cpp b/src/mongo/db/auth/role_graph_builtin_roles.cpp
index deaee655416..479cc0de9fa 100644
--- a/src/mongo/db/auth/role_graph_builtin_roles.cpp
+++ b/src/mongo/db/auth/role_graph_builtin_roles.cpp
@@ -149,6 +149,7 @@ namespace {
// DB admin role
dbAdminRoleActions
+ << ActionType::bypassDocumentValidation
<< ActionType::collMod
<< ActionType::collStats // clusterMonitor gets this also
<< ActionType::compact
@@ -555,11 +556,15 @@ namespace {
void addRestorePrivileges(PrivilegeVector* privileges) {
ActionSet actions;
- actions << ActionType::insert
- << ActionType::dropCollection
- << ActionType::createIndex
- << ActionType::createCollection
- << ActionType::collMod;
+ actions
+ << ActionType::bypassDocumentValidation
+ << ActionType::collMod
+ << ActionType::createCollection
+ << ActionType::createIndex
+ << ActionType::dropCollection
+ << ActionType::insert
+ ;
+
Privilege::addPrivilegeToPrivilegeVector(
privileges,
Privilege(ResourcePattern::forAnyNormalResource(), actions));
diff --git a/src/mongo/db/catalog/document_validation.h b/src/mongo/db/catalog/document_validation.h
index 0f838f6184a..a0e6cb349e3 100644
--- a/src/mongo/db/catalog/document_validation.h
+++ b/src/mongo/db/catalog/document_validation.h
@@ -29,6 +29,7 @@
#pragma once
#include "mongo/base/disallow_copying.h"
+#include "mongo/base/string_data.h"
#include "mongo/db/operation_context.h"
namespace mongo {
@@ -39,6 +40,14 @@ namespace mongo {
*/
extern const OperationContext::Decoration<bool> documentValidationDisabled;
+ inline StringData bypassDocumentValidationCommandOption() {
+ return "bypassDocumentValidation";
+ }
+
+ inline bool shouldBypassDocumentValidationforCommand(const BSONObj& cmdObj) {
+ return cmdObj[bypassDocumentValidationCommandOption()].trueValue();
+ }
+
/**
* Disables document validation on a single OperationContext while in scope.
* Resets to original value when leaving scope so they are safe to nest.
diff --git a/src/mongo/db/commands/clone.cpp b/src/mongo/db/commands/clone.cpp
index 78b576553b3..76a801caa35 100644
--- a/src/mongo/db/commands/clone.cpp
+++ b/src/mongo/db/commands/clone.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/cloner.h"
#include "mongo/db/commands.h"
#include "mongo/db/commands/copydb.h"
@@ -80,6 +81,10 @@ namespace mongo {
ActionSet actions;
actions.addAction(ActionType::insert);
actions.addAction(ActionType::createIndex);
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ actions.addAction(ActionType::bypassDocumentValidation);
+ }
+
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
ResourcePattern::forDatabaseName(dbname), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -94,6 +99,10 @@ namespace mongo {
string& errmsg,
BSONObjBuilder& result) {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmdObj))
+ maybeDisableValidation.emplace(txn);
+
string from = cmdObj.getStringField("clone");
if ( from.empty() )
return false;
diff --git a/src/mongo/db/commands/clone_collection.cpp b/src/mongo/db/commands/clone_collection.cpp
index e924e870e33..d0be61d3955 100644
--- a/src/mongo/db/commands/clone_collection.cpp
+++ b/src/mongo/db/commands/clone_collection.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/cloner.h"
#include "mongo/db/commands.h"
#include "mongo/db/commands/copydb.h"
@@ -85,6 +86,9 @@ namespace mongo {
ActionSet actions;
actions.addAction(ActionType::insert);
actions.addAction(ActionType::createIndex); // SERVER-11418
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ actions.addAction(ActionType::bypassDocumentValidation);
+ }
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
ResourcePattern::forExactNamespace(NamespaceString(ns)), actions)) {
@@ -107,6 +111,10 @@ namespace mongo {
string& errmsg,
BSONObjBuilder& result) {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmdObj))
+ maybeDisableValidation.emplace(txn);
+
string fromhost = cmdObj.getStringField("from");
if ( fromhost.empty() ) {
errmsg = "missing 'from' parameter";
diff --git a/src/mongo/db/commands/copydb.cpp b/src/mongo/db/commands/copydb.cpp
index 415f3b396c7..1d5a5b590b0 100644
--- a/src/mongo/db/commands/copydb.cpp
+++ b/src/mongo/db/commands/copydb.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/cloner.h"
#include "mongo/db/commands.h"
#include "mongo/db/commands/copydb.h"
@@ -128,6 +129,10 @@ namespace mongo {
string& errmsg,
BSONObjBuilder& result) {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmdObj))
+ maybeDisableValidation.emplace(txn);
+
string fromhost = cmdObj.getStringField("fromhost");
bool fromSelf = fromhost.empty();
if ( fromSelf ) {
diff --git a/src/mongo/db/commands/copydb_common.cpp b/src/mongo/db/commands/copydb_common.cpp
index ca2d78e937d..778fc39a93c 100644
--- a/src/mongo/db/commands/copydb_common.cpp
+++ b/src/mongo/db/commands/copydb_common.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/client_basic.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
@@ -64,6 +65,10 @@ namespace copydb {
ActionSet actions;
actions.addAction(ActionType::insert);
actions.addAction(ActionType::createIndex);
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ actions.addAction(ActionType::bypassDocumentValidation);
+ }
+
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
ResourcePattern::forDatabaseName(todb), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 7de1b1ff966..099750539ab 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -38,6 +38,7 @@
#include "mongo/base/status_with.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
@@ -426,6 +427,10 @@ namespace {
txn->setWriteConcern(wcResult.getValue());
setupSynchronousCommit(txn);
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmdObj))
+ maybeDisableValidation.emplace(txn);
+
// We may encounter a WriteConflictException when creating a collection during an
// upsert, even when holding the exclusive lock on the database (due to other load on
// the system). The query framework should handle all other WriteConflictExceptions,
diff --git a/src/mongo/db/commands/find_and_modify_common.cpp b/src/mongo/db/commands/find_and_modify_common.cpp
index 796b6db415a..a5f0e91fb8d 100644
--- a/src/mongo/db/commands/find_and_modify_common.cpp
+++ b/src/mongo/db/commands/find_and_modify_common.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/resource_pattern.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
@@ -50,6 +51,7 @@ namespace find_and_modify {
bool update = cmdObj["update"].trueValue();
bool upsert = cmdObj["upsert"].trueValue();
bool remove = cmdObj["remove"].trueValue();
+ bool bypassDocumentValidation = shouldBypassDocumentValidationforCommand(cmdObj);
ActionSet actions;
actions.addAction(ActionType::find);
@@ -62,6 +64,9 @@ namespace find_and_modify {
if (remove) {
actions.addAction(ActionType::remove);
}
+ if (bypassDocumentValidation) {
+ actions.addAction(ActionType::bypassDocumentValidation);
+ }
ResourcePattern resource(commandTemplate->parseResourcePattern(dbname, cmdObj));
uassert(17137, "Invalid target namespace " + resource.toString(),
resource.isExactNamespacePattern());
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 54d971dd212..e723e533889 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
#include "mongo/db/db.h"
@@ -1287,6 +1288,10 @@ namespace mongo {
BSONObjBuilder& result) {
Timer t;
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmd))
+ maybeDisableValidation.emplace(txn);
+
if (txn->getClient()->isInDirectClient()) {
return appendCommandStatus(result,
Status(ErrorCodes::IllegalOperation,
@@ -1569,6 +1574,10 @@ namespace mongo {
int,
string& errmsg,
BSONObjBuilder& result) {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (shouldBypassDocumentValidationforCommand(cmdObj))
+ maybeDisableValidation.emplace(txn);
+
ShardedConnectionInfo::addHook();
// legacy name
string shardedOutputCollection = cmdObj["shardedOutputCollection"].valuestrsafe();
diff --git a/src/mongo/db/commands/mr_common.cpp b/src/mongo/db/commands/mr_common.cpp
index cf507b2aded..02a5afe1ca5 100644
--- a/src/mongo/db/commands/mr_common.cpp
+++ b/src/mongo/db/commands/mr_common.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/util/mongoutils/str.h"
@@ -126,6 +127,10 @@ namespace mongo {
outputActions.addAction(ActionType::update);
}
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ outputActions.addAction(ActionType::bypassDocumentValidation);
+ }
+
ResourcePattern outputResource(
ResourcePattern::forExactNamespace(
NamespaceString(outputOptions.finalNamespace)));
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index e65ffe04f85..3c2750dfb16 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -38,6 +38,7 @@
#include "mongo/base/error_codes.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_create.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
@@ -734,6 +735,10 @@ namespace mongo {
void WriteBatchExecutor::bulkExecute( const BatchedCommandRequest& request,
std::vector<BatchedUpsertDetail*>* upsertedIds,
std::vector<WriteErrorDetail*>* errors ) {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (request.shouldBypassValidation()) {
+ maybeDisableValidation.emplace(_txn);
+ }
if ( request.getBatchType() == BatchedCommandRequest::BatchType_Insert ) {
execInserts( request, errors );
diff --git a/src/mongo/db/commands/write_commands/write_commands_common.cpp b/src/mongo/db/commands/write_commands/write_commands_common.cpp
index 72c132ae1c0..92265e72507 100644
--- a/src/mongo/db/commands/write_commands/write_commands_common.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands_common.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/util/assert_util.h"
namespace mongo {
@@ -50,12 +51,16 @@ namespace auth {
const BSONObj& cmdObj ) {
vector<Privilege> privileges;
+ ActionSet actionsOnCommandNSSS;
+
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ actionsOnCommandNSSS.addAction(ActionType::bypassDocumentValidation);
+ }
if ( cmdType == BatchedCommandRequest::BatchType_Insert ) {
if ( !cmdNSS.isSystemDotIndexes() ) {
- privileges.push_back( Privilege( ResourcePattern::forExactNamespace( cmdNSS ),
- ActionType::insert ) );
+ actionsOnCommandNSSS.addAction(ActionType::insert);
}
else {
// Special-case indexes until we have a command
@@ -70,23 +75,22 @@ namespace auth {
}
}
else if ( cmdType == BatchedCommandRequest::BatchType_Update ) {
-
- ActionSet actions;
- actions.addAction( ActionType::update );
+ actionsOnCommandNSSS.addAction(ActionType::update);
// Upsert also requires insert privs
if ( BatchedCommandRequest::containsUpserts( cmdObj ) ) {
- actions.addAction( ActionType::insert );
+ actionsOnCommandNSSS.addAction(ActionType::insert);
}
-
- privileges.push_back( Privilege( ResourcePattern::forExactNamespace( cmdNSS ),
- actions ) );
-
}
else {
fassert( 17251, cmdType == BatchedCommandRequest::BatchType_Delete );
- privileges.push_back( Privilege( ResourcePattern::forExactNamespace( cmdNSS ),
- ActionType::remove ) );
+ actionsOnCommandNSSS.addAction(ActionType::remove);
+ }
+
+
+ if (!actionsOnCommandNSSS.empty()) {
+ privileges.emplace_back(ResourcePattern::forExactNamespace(cmdNSS),
+ actionsOnCommandNSSS);
}
if ( authzSession->isAuthorizedForPrivileges( privileges ) )
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h
index a2b6c2225da..fd88833611d 100644
--- a/src/mongo/db/pipeline/document_source.h
+++ b/src/mongo/db/pipeline/document_source.h
@@ -233,6 +233,11 @@ namespace mongo {
virtual bool isCapped(const NamespaceString& ns) = 0;
+ /**
+ * Inserts 'objs' into 'ns' and returns the "detailed" last error object.
+ */
+ virtual BSONObj insert(const NamespaceString& ns, const std::vector<BSONObj>& objs) = 0;
+
// Add new methods as needed.
};
@@ -711,7 +716,7 @@ namespace mongo {
// Sets _tempsNs and prepares it to receive data.
void prepTempCollection();
- void spill(DBClientBase* conn, const std::vector<BSONObj>& toInsert);
+ void spill(const std::vector<BSONObj>& toInsert);
bool _done;
diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp
index fb58cb1565a..bdb8d1d7055 100644
--- a/src/mongo/db/pipeline/document_source_out.cpp
+++ b/src/mongo/db/pipeline/document_source_out.cpp
@@ -109,9 +109,8 @@ namespace mongo {
}
}
- void DocumentSourceOut::spill(DBClientBase* conn, const vector<BSONObj>& toInsert) {
- conn->insert(_tempNs.ns(), toInsert);
- BSONObj err = conn->getLastErrorDetailed();
+ void DocumentSourceOut::spill(const vector<BSONObj>& toInsert) {
+ BSONObj err = _mongod->insert(_tempNs, toInsert);
uassert(16996, str::stream() << "insert for $out failed: " << err,
DBClientWithCommands::getLastErrorString(err).empty());
}
@@ -136,7 +135,7 @@ namespace mongo {
BSONObj toInsert = next->toBson();
bufferedBytes += toInsert.objsize();
if (!bufferedObjects.empty() && bufferedBytes > BSONObjMaxUserSize) {
- spill(conn, bufferedObjects);
+ spill(bufferedObjects);
bufferedObjects.clear();
bufferedBytes = toInsert.objsize();
}
@@ -144,7 +143,7 @@ namespace mongo {
}
if (!bufferedObjects.empty())
- spill(conn, bufferedObjects);
+ spill(bufferedObjects);
// Checking again to make sure we didn't become sharded while running.
uassert(17018, str::stream() << "namespace '" << _outputNs.ns()
diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h
index 5b4b6f55acf..96cce9e4b4f 100644
--- a/src/mongo/db/pipeline/expression_context.h
+++ b/src/mongo/db/pipeline/expression_context.h
@@ -39,12 +39,8 @@ namespace mongo {
struct ExpressionContext : public IntrusiveCounterUnsigned {
public:
ExpressionContext(OperationContext* opCtx, const NamespaceString& ns)
- : inShard(false)
- , inRouter(false)
- , extSortAllowed(false)
- , ns(ns)
+ : ns(ns)
, opCtx(opCtx)
- , interruptCounter(interruptCheckPeriod)
{}
/** Used by a pipeline to check for interrupts so that killOp() works.
@@ -54,18 +50,20 @@ namespace mongo {
if (opCtx && --interruptCounter == 0) { // XXX SERVER-13931 for opCtx check
// The checkForInterrupt could be expensive, at least in relative terms.
opCtx->checkForInterrupt();
- interruptCounter = interruptCheckPeriod;
+ interruptCounter = kInterruptCheckPeriod;
}
}
- bool inShard;
- bool inRouter;
- bool extSortAllowed;
+ bool inShard = false;
+ bool inRouter = false;
+ bool extSortAllowed = false;
+ bool bypassDocumentValidation = false;
+
NamespaceString ns;
std::string tempDir; // Defaults to empty to prevent external sorting in mongos.
OperationContext* opCtx;
- static const int interruptCheckPeriod = 128;
- int interruptCounter; // when 0, check interruptStatus
+ static const int kInterruptCheckPeriod = 128;
+ int interruptCounter = kInterruptCheckPeriod; // when 0, check interruptStatus
};
}
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp
index de7b7590bff..4804189982d 100644
--- a/src/mongo/db/pipeline/pipeline.cpp
+++ b/src/mongo/db/pipeline/pipeline.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/pipeline/accumulator.h"
@@ -162,6 +163,11 @@ namespace mongo {
continue;
}
+ if (pFieldName == bypassDocumentValidationCommandOption()) {
+ pCtx->bypassDocumentValidation = cmdElement.trueValue();
+ continue;
+ }
+
/* we didn't recognize a field in the command */
ostringstream sb;
sb << "unrecognized field '" << cmdElement.fieldName() << "'";
@@ -353,6 +359,10 @@ namespace mongo {
ActionSet actions;
actions.addAction(ActionType::remove);
actions.addAction(ActionType::insert);
+ if (shouldBypassDocumentValidationforCommand(cmdObj)) {
+ actions.addAction(ActionType::bypassDocumentValidation);
+ }
+
out->push_back(Privilege(ResourcePattern::forExactNamespace(outputNs), actions));
}
}
@@ -481,6 +491,10 @@ namespace mongo {
serialized.setField("allowDiskUse", Value(true));
}
+ if (pCtx->bypassDocumentValidation) {
+ serialized.setField(bypassDocumentValidationCommandOption(), Value(true));
+ }
+
return serialized.freeze();
}
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index 51a4a6ef4cd..2709cc7f8d5 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -36,6 +36,7 @@
#include "mongo/client/dbclientinterface.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/db_raii.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/pipeline/document_source.h"
@@ -51,31 +52,40 @@ namespace mongo {
using std::string;
namespace {
- class MongodImplementation : public DocumentSourceNeedsMongod::MongodInterface {
+ class MongodImplementation final : public DocumentSourceNeedsMongod::MongodInterface {
public:
MongodImplementation(const intrusive_ptr<ExpressionContext>& ctx)
: _ctx(ctx)
, _client(ctx->opCtx)
{}
- DBClientBase* directClient() {
+ DBClientBase* directClient() final {
// opCtx may have changed since our last call
invariant(_ctx->opCtx);
_client.setOpCtx(_ctx->opCtx);
return &_client;
}
- bool isSharded(const NamespaceString& ns) {
+ bool isSharded(const NamespaceString& ns) final {
const ChunkVersion unsharded(0, 0, OID());
return !(shardingState.getVersion(ns.ns()).isWriteCompatibleWith(unsharded));
}
- bool isCapped(const NamespaceString& ns) {
+ bool isCapped(const NamespaceString& ns) final {
AutoGetCollectionForRead ctx(_ctx->opCtx, ns.ns());
Collection* collection = ctx.getCollection();
return collection && collection->isCapped();
}
+ BSONObj insert(const NamespaceString& ns, const std::vector<BSONObj>& objs) final {
+ boost::optional<DisableDocumentValidation> maybeDisableValidation;
+ if (_ctx->bypassDocumentValidation)
+ maybeDisableValidation.emplace(_ctx->opCtx);
+
+ _client.insert(ns.ns(), objs);
+ return _client.getLastErrorDetailed();
+ }
+
private:
intrusive_ptr<ExpressionContext> _ctx;
DBDirectClient _client;