summaryrefslogtreecommitdiff
path: root/src/mongo/db/ops/parsed_update.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/ops/parsed_update.cpp')
-rw-r--r--src/mongo/db/ops/parsed_update.cpp206
1 files changed, 100 insertions, 106 deletions
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index d4651371e3f..80138e0385d 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -35,126 +35,120 @@
namespace mongo {
- ParsedUpdate::ParsedUpdate(OperationContext* txn, const UpdateRequest* request) :
- _txn(txn),
- _request(request),
- _driver(UpdateDriver::Options()),
- _canonicalQuery() { }
-
- Status ParsedUpdate::parseRequest() {
- // It is invalid to request that the UpdateStage return the prior or newly-updated version
- // of a document during a multi-update.
- invariant(!(_request->shouldReturnAnyDocs() && _request->isMulti()));
-
- // It is invalid to request that a ProjectionStage be applied to the UpdateStage if the
- // UpdateStage would not return any document.
- invariant(_request->getProj().isEmpty() || _request->shouldReturnAnyDocs());
-
- // We parse the update portion before the query portion because the dispostion of the update
- // may determine whether or not we need to produce a CanonicalQuery at all. For example, if
- // the update involves the positional-dollar operator, we must have a CanonicalQuery even if
- // it isn't required for query execution.
- Status status = parseUpdate();
- if (!status.isOK())
- return status;
- status = parseQuery();
- if (!status.isOK())
- return status;
- return Status::OK();
- }
-
- Status ParsedUpdate::parseQuery() {
- dassert(!_canonicalQuery.get());
+ParsedUpdate::ParsedUpdate(OperationContext* txn, const UpdateRequest* request)
+ : _txn(txn), _request(request), _driver(UpdateDriver::Options()), _canonicalQuery() {}
+
+Status ParsedUpdate::parseRequest() {
+ // It is invalid to request that the UpdateStage return the prior or newly-updated version
+ // of a document during a multi-update.
+ invariant(!(_request->shouldReturnAnyDocs() && _request->isMulti()));
+
+ // It is invalid to request that a ProjectionStage be applied to the UpdateStage if the
+ // UpdateStage would not return any document.
+ invariant(_request->getProj().isEmpty() || _request->shouldReturnAnyDocs());
+
+ // We parse the update portion before the query portion because the dispostion of the update
+ // may determine whether or not we need to produce a CanonicalQuery at all. For example, if
+ // the update involves the positional-dollar operator, we must have a CanonicalQuery even if
+ // it isn't required for query execution.
+ Status status = parseUpdate();
+ if (!status.isOK())
+ return status;
+ status = parseQuery();
+ if (!status.isOK())
+ return status;
+ return Status::OK();
+}
- if (!_driver.needMatchDetails() && CanonicalQuery::isSimpleIdQuery(_request->getQuery())) {
- return Status::OK();
- }
+Status ParsedUpdate::parseQuery() {
+ dassert(!_canonicalQuery.get());
- return parseQueryToCQ();
+ if (!_driver.needMatchDetails() && CanonicalQuery::isSimpleIdQuery(_request->getQuery())) {
+ return Status::OK();
}
- Status ParsedUpdate::parseQueryToCQ() {
- dassert(!_canonicalQuery.get());
-
- CanonicalQuery* cqRaw;
- const WhereCallbackReal whereCallback(_txn, _request->getNamespaceString().db());
-
- // Limit should only used for the findAndModify command when a sort is specified. If a sort
- // is requested, we want to use a top-k sort for efficiency reasons, so should pass the
- // limit through. Generally, a update stage expects to be able to skip documents that were
- // deleted/modified under it, but a limit could inhibit that and give an EOF when the update
- // has not actually updated a document. This behavior is fine for findAndModify, but should
- // not apply to update in general.
- long long limit = (!_request->isMulti() && !_request->getSort().isEmpty()) ? -1 : 0;
-
- // The projection needs to be applied after the update operation, so we specify an empty
- // BSONObj as the projection during canonicalization.
- const BSONObj emptyObj;
- Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
- _request->getQuery(),
- _request->getSort(),
- emptyObj, // projection
- 0, // skip
- limit,
- emptyObj, // hint
- emptyObj, // min
- emptyObj, // max
- false, // snapshot
- _request->isExplain(),
- &cqRaw,
- whereCallback);
- if (status.isOK()) {
- _canonicalQuery.reset(cqRaw);
- }
-
- return status;
+ return parseQueryToCQ();
+}
+
+Status ParsedUpdate::parseQueryToCQ() {
+ dassert(!_canonicalQuery.get());
+
+ CanonicalQuery* cqRaw;
+ const WhereCallbackReal whereCallback(_txn, _request->getNamespaceString().db());
+
+ // Limit should only used for the findAndModify command when a sort is specified. If a sort
+ // is requested, we want to use a top-k sort for efficiency reasons, so should pass the
+ // limit through. Generally, a update stage expects to be able to skip documents that were
+ // deleted/modified under it, but a limit could inhibit that and give an EOF when the update
+ // has not actually updated a document. This behavior is fine for findAndModify, but should
+ // not apply to update in general.
+ long long limit = (!_request->isMulti() && !_request->getSort().isEmpty()) ? -1 : 0;
+
+ // The projection needs to be applied after the update operation, so we specify an empty
+ // BSONObj as the projection during canonicalization.
+ const BSONObj emptyObj;
+ Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
+ _request->getQuery(),
+ _request->getSort(),
+ emptyObj, // projection
+ 0, // skip
+ limit,
+ emptyObj, // hint
+ emptyObj, // min
+ emptyObj, // max
+ false, // snapshot
+ _request->isExplain(),
+ &cqRaw,
+ whereCallback);
+ if (status.isOK()) {
+ _canonicalQuery.reset(cqRaw);
}
- Status ParsedUpdate::parseUpdate() {
- const NamespaceString& ns(_request->getNamespaceString());
+ return status;
+}
- // Should the modifiers validate their embedded docs via okForStorage
- // Only user updates should be checked. Any system or replication stuff should pass through.
- // Config db docs shouldn't get checked for valid field names since the shard key can have
- // a dot (".") in it.
- const bool shouldValidate = !(!_txn->writesAreReplicated() ||
- ns.isConfigDB() ||
- _request->isFromMigration());
+Status ParsedUpdate::parseUpdate() {
+ const NamespaceString& ns(_request->getNamespaceString());
- _driver.setLogOp(true);
- _driver.setModOptions(ModifierInterface::Options(!_txn->writesAreReplicated(),
- shouldValidate));
+ // Should the modifiers validate their embedded docs via okForStorage
+ // Only user updates should be checked. Any system or replication stuff should pass through.
+ // Config db docs shouldn't get checked for valid field names since the shard key can have
+ // a dot (".") in it.
+ const bool shouldValidate =
+ !(!_txn->writesAreReplicated() || ns.isConfigDB() || _request->isFromMigration());
- return _driver.parse(_request->getUpdates(), _request->isMulti());
- }
+ _driver.setLogOp(true);
+ _driver.setModOptions(ModifierInterface::Options(!_txn->writesAreReplicated(), shouldValidate));
- bool ParsedUpdate::canYield() const {
- return !_request->isGod() &&
- PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() &&
- !isIsolated();
- }
+ return _driver.parse(_request->getUpdates(), _request->isMulti());
+}
- bool ParsedUpdate::isIsolated() const {
- return _canonicalQuery.get()
- ? QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC)
- : LiteParsedQuery::isQueryIsolated(_request->getQuery());
- }
+bool ParsedUpdate::canYield() const {
+ return !_request->isGod() && PlanExecutor::YIELD_AUTO == _request->getYieldPolicy() &&
+ !isIsolated();
+}
- bool ParsedUpdate::hasParsedQuery() const {
- return _canonicalQuery.get() != NULL;
- }
+bool ParsedUpdate::isIsolated() const {
+ return _canonicalQuery.get()
+ ? QueryPlannerCommon::hasNode(_canonicalQuery->root(), MatchExpression::ATOMIC)
+ : LiteParsedQuery::isQueryIsolated(_request->getQuery());
+}
- CanonicalQuery* ParsedUpdate::releaseParsedQuery() {
- invariant(_canonicalQuery.get() != NULL);
- return _canonicalQuery.release();
- }
+bool ParsedUpdate::hasParsedQuery() const {
+ return _canonicalQuery.get() != NULL;
+}
- const UpdateRequest* ParsedUpdate::getRequest() const {
- return _request;
- }
+CanonicalQuery* ParsedUpdate::releaseParsedQuery() {
+ invariant(_canonicalQuery.get() != NULL);
+ return _canonicalQuery.release();
+}
- UpdateDriver* ParsedUpdate::getDriver() {
- return &_driver;
- }
+const UpdateRequest* ParsedUpdate::getRequest() const {
+ return _request;
+}
+
+UpdateDriver* ParsedUpdate::getDriver() {
+ return &_driver;
+}
} // namespace mongo