summaryrefslogtreecommitdiff
path: root/src/mongo/db/ops/parsed_update.cpp
diff options
context:
space:
mode:
authorCharlie <charlie.swanson@mongodb.com>2015-04-14 10:27:18 -0400
committerCharlie <charlie.swanson@mongodb.com>2015-04-14 10:27:18 -0400
commit7a36b1598c45ea07a4713d4630fee204ff782e96 (patch)
tree4f8f67db69d5ac3f7412f1d136416f534fefd135 /src/mongo/db/ops/parsed_update.cpp
parent9637c0ae2721a07386af4fb4c402ee061ed7532f (diff)
downloadmongo-7a36b1598c45ea07a4713d4630fee204ff782e96.tar.gz
SERVER-16063 Rewrite the findAndModify command.
Changed UpdateStage to return the prior or newly-updated version of a document if request. also changed DeleteStage to return the deleted document if requested. Added explain support to the findAndModify command.
Diffstat (limited to 'src/mongo/db/ops/parsed_update.cpp')
-rw-r--r--src/mongo/db/ops/parsed_update.cpp29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index 9e084b2dfe5..d4651371e3f 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -42,9 +42,13 @@ namespace mongo {
_canonicalQuery() { }
Status ParsedUpdate::parseRequest() {
- // It is invalid to request that the update plan stores a copy of the resulting document
- // if it is a multi-update.
- invariant(!(_request->shouldStoreResultDoc() && _request->isMulti()));
+ // 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
@@ -75,8 +79,27 @@ namespace mongo {
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);