summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
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/pipeline
parent22de12dd4ac510cd2a37b643eb528673f651e21b (diff)
downloadmongo-463d3343d559590d60cfd5c48ac98ad675d5390e.tar.gz
SERVER-18227 Add bypassDocumentValidation option to commands that need it
Diffstat (limited to 'src/mongo/db/pipeline')
-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
5 files changed, 47 insertions, 21 deletions
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;