summaryrefslogtreecommitdiff
path: root/src/mongo/db/query
diff options
context:
space:
mode:
authorJason Zhang <jason.zhang@mongodb.com>2023-01-26 03:51:07 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-01-26 05:16:57 +0000
commitbe8fd031fb851f5c0c2288585abafd92439c8d0a (patch)
treef1cb7b7e5c35cbf7088dbb4702b8d435391422e0 /src/mongo/db/query
parent63970dc922c2b307c59a9543613f41714fb1b6d6 (diff)
downloadmongo-be8fd031fb851f5c0c2288585abafd92439c8d0a.tar.gz
SERVER-70506 Support retryability for updateOne, deleteOne, and findAndModify
Diffstat (limited to 'src/mongo/db/query')
-rw-r--r--src/mongo/db/query/cursor_response.cpp28
-rw-r--r--src/mongo/db/query/cursor_response.h13
-rw-r--r--src/mongo/db/query/cursor_response.idl9
3 files changed, 46 insertions, 4 deletions
diff --git a/src/mongo/db/query/cursor_response.cpp b/src/mongo/db/query/cursor_response.cpp
index d53a24c7c5f..1940e3def4d 100644
--- a/src/mongo/db/query/cursor_response.cpp
+++ b/src/mongo/db/query/cursor_response.cpp
@@ -57,6 +57,7 @@ const char kBatchDocSequenceFieldInitial[] = "cursor.firstBatch";
const char kPostBatchResumeTokenField[] = "postBatchResumeToken";
const char kPartialResultsReturnedField[] = "partialResultsReturned";
const char kInvalidatedField[] = "invalidated";
+const char kWasStatementExecuted[] = "$_wasStatementExecuted";
} // namespace
@@ -84,6 +85,10 @@ void CursorResponseBuilder::done(CursorId cursorId, const NamespaceString& curso
_cursorObject->append(kInvalidatedField, _invalidated);
}
+ if (_wasStatementExecuted) {
+ _cursorObject->append(kWasStatementExecuted, _wasStatementExecuted);
+ }
+
_cursorObject->append(kIdField, cursorId);
_cursorObject->append(kNsField, NamespaceStringUtil::serialize(cursorNamespace));
if (_options.atClusterTime) {
@@ -140,7 +145,8 @@ CursorResponse::CursorResponse(NamespaceString nss,
boost::optional<BSONObj> varsField,
boost::optional<std::string> cursorType,
bool partialResultsReturned,
- bool invalidated)
+ bool invalidated,
+ bool wasStatementExecuted)
: _nss(std::move(nss)),
_cursorId(cursorId),
_batch(std::move(batch)),
@@ -150,7 +156,8 @@ CursorResponse::CursorResponse(NamespaceString nss,
_varsField(std::move(varsField)),
_cursorType(std::move(cursorType)),
_partialResultsReturned(partialResultsReturned),
- _invalidated(invalidated) {}
+ _invalidated(invalidated),
+ _wasStatementExecuted(wasStatementExecuted) {}
std::vector<StatusWith<CursorResponse>> CursorResponse::parseFromBSONMany(
const BSONObj& cmdResponse) {
@@ -299,6 +306,16 @@ StatusWith<CursorResponse> CursorResponse::parseFromBSON(const BSONObj& cmdRespo
}
}
+ auto wasStatementExecuted = cursorObj[kWasStatementExecuted];
+ if (wasStatementExecuted) {
+ if (wasStatementExecuted.type() != BSONType::Bool) {
+ return {ErrorCodes::BadValue,
+ str::stream() << kWasStatementExecuted
+ << " format is invalid; expected Bool, but found: "
+ << wasStatementExecuted.type()};
+ }
+ }
+
auto writeConcernError = cmdResponse["writeConcernError"];
if (writeConcernError && writeConcernError.type() != BSONType::Object) {
@@ -317,7 +334,8 @@ StatusWith<CursorResponse> CursorResponse::parseFromBSON(const BSONObj& cmdRespo
varsElt ? varsElt.Obj().getOwned() : boost::optional<BSONObj>{},
typeElt ? boost::make_optional<std::string>(typeElt.String()) : boost::none,
partialResultsReturned.trueValue(),
- invalidatedElem.trueValue()}};
+ invalidatedElem.trueValue(),
+ wasStatementExecuted.trueValue()}};
}
void CursorResponse::addToBSON(CursorResponse::ResponseType responseType,
@@ -351,6 +369,10 @@ void CursorResponse::addToBSON(CursorResponse::ResponseType responseType,
cursorBuilder.append(kInvalidatedField, _invalidated);
}
+ if (_wasStatementExecuted) {
+ cursorBuilder.append(kWasStatementExecuted, _wasStatementExecuted);
+ }
+
cursorBuilder.doneFast();
builder->append("ok", 1.0);
diff --git a/src/mongo/db/query/cursor_response.h b/src/mongo/db/query/cursor_response.h
index 7b33b71e1d5..87f5f22c263 100644
--- a/src/mongo/db/query/cursor_response.h
+++ b/src/mongo/db/query/cursor_response.h
@@ -99,6 +99,10 @@ public:
_invalidated = true;
}
+ void setWasStatementExecuted(bool wasStatementExecuted) {
+ _wasStatementExecuted = true;
+ }
+
long long numDocs() const {
return _numDocs;
}
@@ -135,6 +139,7 @@ private:
BSONObj _postBatchResumeToken;
bool _partialResultsReturned = false;
bool _invalidated = false;
+ bool _wasStatementExecuted = false;
};
/**
@@ -216,7 +221,8 @@ public:
boost::optional<BSONObj> varsField = boost::none,
boost::optional<std::string> cursorType = boost::none,
bool partialResultsReturned = false,
- bool invalidated = false);
+ bool invalidated = false,
+ bool wasStatementExecuted = false);
CursorResponse(CursorResponse&& other) = default;
CursorResponse& operator=(CursorResponse&& other) = default;
@@ -269,6 +275,10 @@ public:
return _invalidated;
}
+ bool getWasStatementExecuted() const {
+ return _wasStatementExecuted;
+ }
+
/**
* Converts this response to its raw BSON representation.
*/
@@ -289,6 +299,7 @@ private:
boost::optional<std::string> _cursorType;
bool _partialResultsReturned = false;
bool _invalidated = false;
+ bool _wasStatementExecuted = false;
};
} // namespace mongo
diff --git a/src/mongo/db/query/cursor_response.idl b/src/mongo/db/query/cursor_response.idl
index af264710874..391beb38c35 100644
--- a/src/mongo/db/query/cursor_response.idl
+++ b/src/mongo/db/query/cursor_response.idl
@@ -76,6 +76,15 @@ structs:
description: "Boolean represents if the cursor has been invalidated."
type: optionalBool
stability: stable
+ $_wasStatementExecuted:
+ description: "An optional field set to true if a write without shard key had already
+ applied the write. To provide some context, this internal field is
+ used by the two phase write without shard key protocol introduced in
+ PM-1632 to support retryable writes for updateOne without shard key,
+ deleteOne without shard key, and findAndModify without shard key."
+ type: optionalBool
+ cpp_name: wasStatementExecuted
+ stability: internal
InitialResponseCursor:
description: "A struct representing an initial response cursor."