summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/ops/write_ops.cpp16
-rw-r--r--src/mongo/db/ops/write_ops_parsers.h14
-rw-r--r--src/mongo/db/pipeline/aggregation_request_helper.cpp16
-rw-r--r--src/mongo/db/pipeline/aggregation_request_helper.h19
-rw-r--r--src/mongo/db/pipeline/aggregation_request_test.cpp17
-rw-r--r--src/mongo/db/query/hint_parser.cpp8
-rw-r--r--src/mongo/db/query/max_time_ms_parser.cpp4
-rw-r--r--src/mongo/db/query/max_time_ms_parser.h4
-rw-r--r--src/mongo/db/query/query_request_test.cpp58
-rw-r--r--src/mongo/idl/basic_types.h26
-rw-r--r--src/mongo/idl/idl_parser.cpp16
-rw-r--r--src/mongo/idl/idl_parser.h16
12 files changed, 203 insertions, 11 deletions
diff --git a/src/mongo/db/ops/write_ops.cpp b/src/mongo/db/ops/write_ops.cpp
index 8e00f19713a..f69ad8844bb 100644
--- a/src/mongo/db/ops/write_ops.cpp
+++ b/src/mongo/db/ops/write_ops.cpp
@@ -79,6 +79,10 @@ void checkOpCountForCommand(const T& op, size_t numOps) {
namespace write_ops {
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool readMultiDeleteProperty(const BSONElement& limitElement) {
// Using a double to avoid throwing away illegal fractional portion. Don't want to accept 0.5
// here
@@ -90,6 +94,10 @@ bool readMultiDeleteProperty(const BSONElement& limitElement) {
return limit == 0;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder) {
builder->append(fieldName, isMulti ? 0 : 1);
}
@@ -328,6 +336,10 @@ write_ops::UpdateModification::UpdateModification(const BSONObj& update, Classic
write_ops::UpdateModification::UpdateModification(std::vector<BSONObj> pipeline)
: _update{PipelineUpdate{std::move(pipeline)}} {}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
write_ops::UpdateModification write_ops::UpdateModification::parseFromBSON(BSONElement elem) {
return UpdateModification(elem);
}
@@ -363,6 +375,10 @@ write_ops::UpdateModification::Type write_ops::UpdateModification::type() const
_update);
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void write_ops::UpdateModification::serializeToBSON(StringData fieldName,
BSONObjBuilder* bob) const {
diff --git a/src/mongo/db/ops/write_ops_parsers.h b/src/mongo/db/ops/write_ops_parsers.h
index 20b9f543bc7..900740b271b 100644
--- a/src/mongo/db/ops/write_ops_parsers.h
+++ b/src/mongo/db/ops/write_ops_parsers.h
@@ -51,11 +51,17 @@ constexpr int kRetryableAndTxnBatchWriteBSONSizeOverhead =
/**
* Parses the 'limit' property of a delete entry, which has inverted meaning from the 'multi'
* property of an update.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
bool readMultiDeleteProperty(const BSONElement& limitElement);
/**
* Writes the 'isMulti' value as a limit property.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder);
@@ -100,8 +106,16 @@ public:
/**
* These methods support IDL parsing of the "u" field from the update command and OP_UPDATE.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
static UpdateModification parseFromBSON(BSONElement elem);
+
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const;
// When parsing from legacy OP_UPDATE messages, we receive the "u" field as an object. When an
diff --git a/src/mongo/db/pipeline/aggregation_request_helper.cpp b/src/mongo/db/pipeline/aggregation_request_helper.cpp
index 133e151dae6..5bfa4b7c2a3 100644
--- a/src/mongo/db/pipeline/aggregation_request_helper.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_helper.cpp
@@ -241,6 +241,10 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm
// Custom serializers/deserializers for AggregateCommandRequest.
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
const BSONElement& explainElem) {
uassert(ErrorCodes::TypeMismatch,
@@ -254,6 +258,10 @@ boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
return boost::none;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
StringData fieldName,
BSONObjBuilder* builder) {
@@ -264,6 +272,10 @@ void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
return;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem) {
if (cursorElem.eoo()) {
SimpleCursorOptions cursor;
@@ -284,6 +296,10 @@ mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& curso
return cursor;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeAggregateCursorToBSON(const mongo::SimpleCursorOptions& cursor,
StringData fieldName,
BSONObjBuilder* builder) {
diff --git a/src/mongo/db/pipeline/aggregation_request_helper.h b/src/mongo/db/pipeline/aggregation_request_helper.h
index 631fd87a278..bb447712f7f 100644
--- a/src/mongo/db/pipeline/aggregation_request_helper.h
+++ b/src/mongo/db/pipeline/aggregation_request_helper.h
@@ -131,23 +131,40 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm
/**
* Custom serializers/deserializers for AggregateCommandRequest.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
-
boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
const BSONElement& explainElem);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
StringData fieldName,
BSONObjBuilder* builder);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeAggregateCursorToBSON(const SimpleCursorOptions& cursor,
StringData fieldName,
BSONObjBuilder* builder);
/**
* Parse an aggregation pipeline definition from 'pipelineElem'.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
static std::vector<BSONObj> parsePipelineFromBSON(const BSONElement& pipelineElem) {
std::vector<BSONObj> pipeline;
diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp
index 66bac44423c..947764892b7 100644
--- a/src/mongo/db/pipeline/aggregation_request_test.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_test.cpp
@@ -554,6 +554,23 @@ TEST(AggregationRequestTest, ShouldRejectNoCursorNoExplain) {
aggregation_request_helper::parseFromBSONForTests(nss, cursorRequest.done()).getStatus());
}
+TEST(AggregationRequestTest, ShouldRejectNonObjectCursor) {
+ NamespaceString nss("a.collection");
+ const BSONObj validRequest = fromjson(
+ "{aggregate: 'collection',"
+ "pipeline: [{$match: {a: 'abc'}}],"
+ "cursor: {},"
+ "isMapReduceCommand: true,"
+ "$db: 'a'}");
+ const BSONObj nonObjCursorCommand = fromjson("{cursor: 1}");
+ aggregationRequestParseFailureHelper(
+ nss, validRequest, nonObjCursorCommand, ErrorCodes::TypeMismatch);
+
+ const BSONObj arrayCursorCommand = fromjson("{cursor: []}");
+ aggregationRequestParseFailureHelper(
+ nss, validRequest, arrayCursorCommand, ErrorCodes::TypeMismatch);
+}
+
TEST(AggregationRequestTest, ShouldRejectExplainTrueWithSeparateExplainArg) {
NamespaceString nss("a.collection");
const BSONObj validRequest = fromjson(
diff --git a/src/mongo/db/query/hint_parser.cpp b/src/mongo/db/query/hint_parser.cpp
index d1372d86f55..1de75b84f82 100644
--- a/src/mongo/db/query/hint_parser.cpp
+++ b/src/mongo/db/query/hint_parser.cpp
@@ -33,6 +33,10 @@
namespace mongo {
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseHint(const BSONElement& element) {
if (element.type() == BSONType::String) {
return BSON("$hint" << element.valueStringData());
@@ -44,6 +48,10 @@ BSONObj parseHint(const BSONElement& element) {
MONGO_UNREACHABLE;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeHintToBSON(const BSONObj& hint, StringData fieldName, BSONObjBuilder* builder) {
if (hint.isEmpty())
return;
diff --git a/src/mongo/db/query/max_time_ms_parser.cpp b/src/mongo/db/query/max_time_ms_parser.cpp
index 7f2c84f07ad..054b2b76ead 100644
--- a/src/mongo/db/query/max_time_ms_parser.cpp
+++ b/src/mongo/db/query/max_time_ms_parser.cpp
@@ -62,6 +62,10 @@ StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt) {
return StatusWith<int>(static_cast<int>(maxTimeMSLongLong));
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt) {
return static_cast<int32_t>(uassertStatusOK(parseMaxTimeMS(maxTimeMSElt)));
}
diff --git a/src/mongo/db/query/max_time_ms_parser.h b/src/mongo/db/query/max_time_ms_parser.h
index 1e5ec985c77..d111b480599 100644
--- a/src/mongo/db/query/max_time_ms_parser.h
+++ b/src/mongo/db/query/max_time_ms_parser.h
@@ -56,6 +56,10 @@ static constexpr auto kMaxTimeMSOpOnlyMaxPadding = 100LL;
*/
StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt);
} // namespace mongo
diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp
index e60a04ff79e..8518c0e4661 100644
--- a/src/mongo/db/query/query_request_test.cpp
+++ b/src/mongo/db/query/query_request_test.cpp
@@ -1194,36 +1194,74 @@ TEST(QueryRequestTest, ParseFromCommandForbidExtraOption) {
TEST(QueryRequestTest, ParseMaxTimeMSStringValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << "foo");
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSBoolValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << true);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSNullValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONNULL);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSUndefinedValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONUndefined);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSEmptyObjectValueFails) {
+ const auto emptyObj = BSONObjBuilder().obj();
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << emptyObj);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSNonIntegralValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 100.3);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSOutOfRangeDoubleFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 1e200);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSNegativeValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << -400);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSZeroSucceeds) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 0);
- auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]);
- ASSERT_OK(maxTime);
- ASSERT_EQ(maxTime.getValue(), 0);
+ ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 0);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSEmptyElementSucceeds) {
+ const auto emptyElem = BSONElement();
+ ASSERT_EQ(parseMaxTimeMSForIDL(emptyElem), 0);
}
TEST(QueryRequestTest, ParseMaxTimeMSPositiveInRangeSucceeds) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 300);
- auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]);
- ASSERT_OK(maxTime);
- ASSERT_EQ(maxTime.getValue(), 300);
+ ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 300);
}
TEST(QueryRequestTest, ConvertToAggregationSucceeds) {
diff --git a/src/mongo/idl/basic_types.h b/src/mongo/idl/basic_types.h
index c02366d3c5f..62e191a9bf5 100644
--- a/src/mongo/idl/basic_types.h
+++ b/src/mongo/idl/basic_types.h
@@ -47,6 +47,10 @@ namespace mongo {
*/
class OptionalBool {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static OptionalBool parseFromBSON(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Field '" << element.fieldNameStringData()
@@ -76,6 +80,9 @@ public:
/**
* Serialize this object as a field in a document. If _value is empty, omit the field.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const {
if (_value) {
@@ -85,6 +92,9 @@ public:
/**
* Serialize this object as an element of a BSON array. If _value is empty, omit the entry.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void serializeToBSON(BSONArrayBuilder* builder) const {
if (_value) {
@@ -112,6 +122,10 @@ private:
*/
class IDLAnyType {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static IDLAnyType parseFromBSON(const BSONElement& element) {
return IDLAnyType(element);
}
@@ -119,10 +133,18 @@ public:
IDLAnyType() = default;
IDLAnyType(const BSONElement& element) : _element(element) {}
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const {
builder->appendAs(_element, fieldName);
}
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(BSONArrayBuilder* builder) const {
builder->append(_element);
}
@@ -141,6 +163,10 @@ protected:
*/
class IDLAnyTypeOwned : public IDLAnyType {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static IDLAnyTypeOwned parseFromBSON(const BSONElement& element) {
return IDLAnyTypeOwned(element);
}
diff --git a/src/mongo/idl/idl_parser.cpp b/src/mongo/idl/idl_parser.cpp
index 9cad14bffca..de0ffd40852 100644
--- a/src/mongo/idl/idl_parser.cpp
+++ b/src/mongo/idl/idl_parser.cpp
@@ -341,14 +341,26 @@ std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDa
return output;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob) {}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob) {
if (!obj.isEmpty()) {
bob->append(fieldName, obj);
}
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseOwnedBSON(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Expected field " << element.fieldNameStringData()
@@ -357,6 +369,10 @@ BSONObj parseOwnedBSON(BSONElement element) {
return element.Obj().getOwned();
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool parseBoolean(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Expected field " << element.fieldNameStringData()
diff --git a/src/mongo/idl/idl_parser.h b/src/mongo/idl/idl_parser.h
index 47096c0d117..316ccd06c7e 100644
--- a/src/mongo/idl/idl_parser.h
+++ b/src/mongo/idl/idl_parser.h
@@ -289,12 +289,28 @@ std::vector<std::string> transformVector(const std::vector<StringData>& input);
std::vector<ConstDataRange> transformVector(const std::vector<std::vector<std::uint8_t>>& input);
std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDataRange>& input);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseOwnedBSON(BSONElement element);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool parseBoolean(BSONElement element);
} // namespace mongo