SERVER-104912 core.bson modularity marks (#50551)
GitOrigin-RevId: 84d39d26946778acb03edfa677ff1d25e46d653d
This commit is contained in:
parent
932c71f2eb
commit
5f242626e8
@ -63,6 +63,8 @@ core:
|
||||
- src/mongo/db/stats/counter_ops.h
|
||||
|
||||
core.bson:
|
||||
meta:
|
||||
fully_marked: true
|
||||
files:
|
||||
- src/mongo/bson/
|
||||
# Unsure about the next one but putting here for now:
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "mongo/bson/bsonelement.h"
|
||||
#include "mongo/bson/bsonobjbuilder.h"
|
||||
#include "mongo/util/duration.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
@ -42,7 +43,7 @@ namespace mongo {
|
||||
* e.g. parseDurationFromCount<Seconds> will parse a number of seconds as a Duration.
|
||||
*/
|
||||
template <typename Duration>
|
||||
Duration parseDurationFromCount(const BSONElement& elem) {
|
||||
MONGO_MOD_PUBLIC_FOR_TECHNICAL_REASONS Duration parseDurationFromCount(const BSONElement& elem) {
|
||||
uassert(ErrorCodes::BadValue,
|
||||
str::stream() << "Duration value must be numeric, got: " << typeName(elem.type()),
|
||||
elem.isNumber());
|
||||
@ -55,9 +56,8 @@ Duration parseDurationFromCount(const BSONElement& elem) {
|
||||
* Serializes a Duration to a BSON int32/int64 for the specified units.
|
||||
*/
|
||||
template <typename ToDuration, typename Period>
|
||||
void serializeDurationToCount(const Duration<Period>& duration,
|
||||
StringData fieldName,
|
||||
BSONObjBuilder* builder) {
|
||||
MONGO_MOD_PUBLIC_FOR_TECHNICAL_REASONS void serializeDurationToCount(
|
||||
const Duration<Period>& duration, StringData fieldName, BSONObjBuilder* builder) {
|
||||
builder->append(fieldName, durationCount<ToDuration>(duration));
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -71,10 +72,12 @@ namespace mongo {
|
||||
*
|
||||
* // Use BSONField::operator()() to retrieve the name of the field:
|
||||
* BSONObj obj = BSON(MyCollFields::draining() << 1);
|
||||
*
|
||||
* Deprecated: IDL should now be preferred for imposing structure onto BSON.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class BSONFieldValue {
|
||||
class MONGO_MOD_USE_REPLACEMENT(idl) BSONFieldValue {
|
||||
public:
|
||||
BSONFieldValue(const std::string& name, const T& t) : _name(name), _t(t) {}
|
||||
|
||||
@ -91,7 +94,7 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BSONField {
|
||||
class MONGO_MOD_USE_REPLACEMENT(idl) BSONField {
|
||||
public:
|
||||
BSONField(const std::string& name) : _name(name) {}
|
||||
|
||||
|
||||
@ -33,9 +33,12 @@
|
||||
#include "mongo/bson/bson_validate_gen.h"
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/bson/bsontypes.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
MONGO_MOD_PUBLIC;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
enum ValidationVersion {
|
||||
@ -47,7 +50,7 @@ enum ValidationVersion {
|
||||
|
||||
// When adding new versions of BSON validation, update both this and the range and the
|
||||
// default for the server parameter in src/mongo/bson/bson_validate.idl
|
||||
static constexpr ValidationVersion currentValidationVersion = V2_Column;
|
||||
constexpr inline ValidationVersion currentValidationVersion = V2_Column;
|
||||
|
||||
/**
|
||||
* Checks that the buf holds a BSON object as defined in http://bsonspec.org/spec.html.
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
global:
|
||||
cpp_namespace: "mongo"
|
||||
mod_visibility: public
|
||||
|
||||
imports:
|
||||
- "mongo/db/basic_types.idl"
|
||||
|
||||
@ -31,6 +31,9 @@
|
||||
|
||||
#include "mongo/base/string_data_comparator.h"
|
||||
#include "mongo/bson/bsonobj_comparator_interface.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
MONGO_MOD_PUBLIC;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
|
||||
@ -33,9 +33,12 @@
|
||||
#include "mongo/bson/bsonelement.h"
|
||||
#include "mongo/bson/bsonelement_comparator_interface.h"
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
MONGO_MOD_PUBLIC;
|
||||
|
||||
namespace mongo {
|
||||
namespace bson {
|
||||
|
||||
|
||||
@ -31,6 +31,9 @@
|
||||
|
||||
#include "mongo/base/string_data_comparator.h"
|
||||
#include "mongo/bson/bsonobj_comparator_interface.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
MONGO_MOD_PUBLIC;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@ mongo_cc_library(
|
||||
mongo_cc_unit_test(
|
||||
name = "bson_util_test",
|
||||
srcs = [
|
||||
"bson_check_test.cpp",
|
||||
"bson_extract_test.cpp",
|
||||
"builder_test.cpp",
|
||||
],
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2018-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mongo/base/error_codes.h"
|
||||
#include "mongo/base/status.h"
|
||||
#include "mongo/base/string_data.h"
|
||||
#include "mongo/bson/bsonelement.h"
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/bson/bsontypes.h"
|
||||
#include "mongo/db/commands.h"
|
||||
#include "mongo/idl/command_generic_argument.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/str.h"
|
||||
#include "mongo/util/string_map.h"
|
||||
|
||||
#include <absl/container/node_hash_map.h>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* Confirms that obj only contains field names where allowed(name) returns true,
|
||||
* and that no field name occurs multiple times.
|
||||
*
|
||||
* On failure, returns BadValue and a message naming the unexpected field or error code 51000 with
|
||||
* a message naming a repeated field. "objectName" is included in the message, for reporting
|
||||
* purposes.
|
||||
*/
|
||||
template <typename Condition>
|
||||
Status bsonCheckOnlyHasFieldsImpl(StringData objectName,
|
||||
const BSONObj& obj,
|
||||
const Condition& allowed) {
|
||||
StringMap<bool> seenFields;
|
||||
for (auto&& e : obj) {
|
||||
const auto name = e.fieldNameStringData();
|
||||
|
||||
if (!allowed(name)) {
|
||||
return Status(ErrorCodes::BadValue,
|
||||
str::stream()
|
||||
<< "Unexpected field " << e.fieldName() << " in " << objectName);
|
||||
}
|
||||
|
||||
bool& seenBefore = seenFields[name];
|
||||
if (!seenBefore) {
|
||||
seenBefore = true;
|
||||
} else {
|
||||
return Status(ErrorCodes::Error(51000),
|
||||
str::stream()
|
||||
<< "Field " << name << " appears multiple times in " << objectName);
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
/**
|
||||
* Like above but only allows fields from the passed-in container.
|
||||
*/
|
||||
template <typename Container>
|
||||
Status bsonCheckOnlyHasFields(StringData objectName,
|
||||
const BSONObj& obj,
|
||||
const Container& allowedFields) {
|
||||
return bsonCheckOnlyHasFieldsImpl(objectName, obj, [&](StringData name) {
|
||||
return std::find(std::begin(allowedFields), std::end(allowedFields), name) !=
|
||||
std::end(allowedFields);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Like above but only allows fields from the passed-in container or are generic command arguments.
|
||||
*/
|
||||
template <typename Container>
|
||||
Status bsonCheckOnlyHasFieldsForCommand(StringData objectName,
|
||||
const BSONObj& obj,
|
||||
const Container& allowedFields) {
|
||||
return bsonCheckOnlyHasFieldsImpl(objectName, obj, [&](StringData name) {
|
||||
return isGenericArgument(name) ||
|
||||
(std::find(std::begin(allowedFields), std::end(allowedFields), name) !=
|
||||
std::end(allowedFields));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a uassert if the type of the elem does not match that provided in expectedType
|
||||
*/
|
||||
inline void checkBSONType(BSONType expectedType, const BSONElement& elem) {
|
||||
uassert(elem.type() == BSONType::eoo ? ErrorCodes::NoSuchKey : ErrorCodes::TypeMismatch,
|
||||
str::stream() << "Wrong type for '" << elem.fieldNameStringData() << "'. Expected a "
|
||||
<< typeName(expectedType) << ", got a " << typeName(elem.type()) << '.',
|
||||
elem.type() == expectedType);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mongo
|
||||
@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2018-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "mongo/bson/util/bson_check.h"
|
||||
|
||||
#include "mongo/bson/bsonmisc.h"
|
||||
#include "mongo/bson/bsonobjbuilder.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace mongo {
|
||||
namespace {
|
||||
|
||||
TEST(BsonCheck, CheckNothingLegal) {
|
||||
ASSERT_OK(bsonCheckOnlyHasFields("", BSONObj(), std::vector<StringData>()));
|
||||
ASSERT_EQUALS(ErrorCodes::BadValue,
|
||||
bsonCheckOnlyHasFields("", BSON("a" << 1), std::vector<StringData>()));
|
||||
}
|
||||
|
||||
const char* const legals[] = {"aField", "anotherField", "thirdField"};
|
||||
|
||||
TEST(BsonCheck, CheckHasOnlyOnEmptyObject) {
|
||||
ASSERT_OK(bsonCheckOnlyHasFields("", BSONObj(), legals));
|
||||
}
|
||||
|
||||
TEST(BsonCheck, CheckHasOnlyLegalFields) {
|
||||
ASSERT_OK(bsonCheckOnlyHasFields("",
|
||||
BSON("aField" << "value"
|
||||
<< "thirdField" << 1 << "anotherField" << 2),
|
||||
legals));
|
||||
ASSERT_OK(bsonCheckOnlyHasFields("",
|
||||
BSON("aField" << "value"
|
||||
<< "thirdField" << 1),
|
||||
legals));
|
||||
|
||||
ASSERT_EQUALS(ErrorCodes::BadValue,
|
||||
bsonCheckOnlyHasFields("",
|
||||
BSON("aField" << "value"
|
||||
<< "illegal" << 4 << "thirdField" << 1),
|
||||
legals));
|
||||
}
|
||||
|
||||
TEST(BsonCheck, CheckNoDuplicates) {
|
||||
ASSERT_EQUALS(51000,
|
||||
bsonCheckOnlyHasFields(
|
||||
"", BSON("aField" << 1 << "anotherField" << 2 << "aField" << 3), legals)
|
||||
.code());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mongo
|
||||
@ -188,21 +188,6 @@ Status bsonExtractOIDField(const BSONObj& object, StringData fieldName, OID* out
|
||||
return status;
|
||||
}
|
||||
|
||||
Status bsonExtractOIDFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
const OID& defaultValue,
|
||||
OID* out) {
|
||||
BSONElement element;
|
||||
Status status = bsonExtractTypedFieldImpl(object, fieldName, BSONType::oid, &element, true);
|
||||
if (status == ErrorCodes::NoSuchKey) {
|
||||
*out = defaultValue;
|
||||
return Status::OK();
|
||||
}
|
||||
if (status.isOK())
|
||||
*out = element.OID();
|
||||
return status;
|
||||
}
|
||||
|
||||
Status bsonExtractStringFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
StringData defaultValue,
|
||||
@ -226,18 +211,6 @@ Status bsonExtractDoubleField(const BSONObj& object, StringData fieldName, doubl
|
||||
return bsonExtractDoubleFieldImpl(object, fieldName, out, false);
|
||||
}
|
||||
|
||||
Status bsonExtractDoubleFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
double defaultValue,
|
||||
double* out) {
|
||||
Status status = bsonExtractDoubleFieldImpl(object, fieldName, out, true);
|
||||
if (status == ErrorCodes::NoSuchKey) {
|
||||
*out = defaultValue;
|
||||
return Status::OK();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
@ -250,31 +223,95 @@ Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
return status;
|
||||
}
|
||||
|
||||
Status bsonExtractIntegerFieldWithDefaultIf(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
std::function<bool(long long)> pred,
|
||||
const std::string& predDescription,
|
||||
long long* out) {
|
||||
Status status = bsonExtractIntegerFieldWithDefault(object, fieldName, defaultValue, out);
|
||||
if (!status.isOK()) {
|
||||
return status;
|
||||
}
|
||||
if (!pred(*out)) {
|
||||
return Status(ErrorCodes::BadValue,
|
||||
str::stream() << "Invalid value in field \"" << fieldName << "\": " << *out
|
||||
<< ": " << predDescription);
|
||||
}
|
||||
return status;
|
||||
////////////////////////////////////////////////////////////
|
||||
// StatusWith variants of the above.
|
||||
|
||||
StatusWith<BSONElement> bsonExtractField(const BSONObj& object, StringData fieldName) {
|
||||
BSONElement out;
|
||||
if (auto st = bsonExtractField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
Status bsonExtractIntegerFieldWithDefaultIf(const BSONObj& object,
|
||||
StatusWith<BSONElement> bsonExtractTypedField(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
std::function<bool(long long)> pred,
|
||||
long long* out) {
|
||||
return bsonExtractIntegerFieldWithDefaultIf(
|
||||
object, fieldName, defaultValue, pred, "constraint failed", out);
|
||||
BSONType type) {
|
||||
BSONElement out;
|
||||
if (auto st = bsonExtractTypedField(object, fieldName, type, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<bool> bsonExtractBooleanField(const BSONObj& object, StringData fieldName) {
|
||||
bool out;
|
||||
if (auto st = bsonExtractBooleanField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<long long> bsonExtractIntegerField(const BSONObj& object, StringData fieldName) {
|
||||
long long out;
|
||||
if (auto st = bsonExtractIntegerField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<double> bsonExtractDoubleField(const BSONObj& object, StringData fieldName) {
|
||||
double out;
|
||||
if (auto st = bsonExtractDoubleField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<std::string> bsonExtractStringField(const BSONObj& object, StringData fieldName) {
|
||||
std::string out;
|
||||
if (auto st = bsonExtractStringField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<Timestamp> bsonExtractTimestampField(const BSONObj& object, StringData fieldName) {
|
||||
Timestamp out;
|
||||
if (auto st = bsonExtractTimestampField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<OID> bsonExtractOIDField(const BSONObj& object, StringData fieldName) {
|
||||
OID out;
|
||||
if (auto st = bsonExtractOIDField(object, fieldName, &out); !st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<bool> bsonExtractBooleanFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
bool defaultValue) {
|
||||
bool out;
|
||||
if (auto st = bsonExtractBooleanFieldWithDefault(object, fieldName, defaultValue, &out);
|
||||
!st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<long long> bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue) {
|
||||
long long out;
|
||||
if (auto st = bsonExtractIntegerFieldWithDefault(object, fieldName, defaultValue, &out);
|
||||
!st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
StatusWith<std::string> bsonExtractStringFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
StringData defaultValue) {
|
||||
std::string out;
|
||||
if (auto st = bsonExtractStringFieldWithDefault(object, fieldName, defaultValue, &out);
|
||||
!st.isOK())
|
||||
return st;
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
@ -30,20 +30,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "mongo/base/status.h"
|
||||
#include "mongo/base/status_with.h"
|
||||
#include "mongo/base/string_data.h"
|
||||
#include "mongo/bson/bsonelement.h"
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/bson/bsontypes.h"
|
||||
#include "mongo/bson/oid.h"
|
||||
#include "mongo/bson/timestamp.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
MONGO_MOD_PUBLIC;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
class BSONObj;
|
||||
class BSONElement;
|
||||
class OID;
|
||||
class Timestamp;
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object".
|
||||
*
|
||||
@ -51,6 +53,7 @@ class Timestamp;
|
||||
* ErrorCodes::NoSuchKey if there are no matches.
|
||||
*/
|
||||
Status bsonExtractField(const BSONObj& object, StringData fieldName, BSONElement* outElement);
|
||||
StatusWith<BSONElement> bsonExtractField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object".
|
||||
@ -64,6 +67,9 @@ Status bsonExtractTypedField(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
BSONType type,
|
||||
BSONElement* outElement);
|
||||
StatusWith<BSONElement> bsonExtractTypedField(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
BSONType type);
|
||||
|
||||
/**
|
||||
* Finds a bool-like element named "fieldName" in "object".
|
||||
@ -74,6 +80,23 @@ Status bsonExtractTypedField(const BSONObj& object,
|
||||
* than Status::OK(), the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractBooleanField(const BSONObj& object, StringData fieldName, bool* out);
|
||||
StatusWith<bool> bsonExtractBooleanField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* If a field named "fieldName" is present, and is either a number or boolean type, stores the
|
||||
* truth value of the field into "*out". If no field named "fieldName" is present, sets "*out"
|
||||
* to "defaultValue". In these cases, returns Status::OK().
|
||||
*
|
||||
* If "fieldName" is present more than once, behavior is undefined. If the found field is not a
|
||||
* boolean or number, returns ErrorCodes::TypeMismatch.
|
||||
*/
|
||||
Status bsonExtractBooleanFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
bool defaultValue,
|
||||
bool* out);
|
||||
StatusWith<bool> bsonExtractBooleanFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
bool defaultValue);
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object" that represents an integral value.
|
||||
@ -86,6 +109,23 @@ Status bsonExtractBooleanField(const BSONObj& object, StringData fieldName, bool
|
||||
* undefined.
|
||||
*/
|
||||
Status bsonExtractIntegerField(const BSONObj& object, StringData fieldName, long long* out);
|
||||
StatusWith<long long> bsonExtractIntegerField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* If a field named "fieldName" is present and is a value of numeric type with an exact 64-bit
|
||||
* integer representation, returns that representation in *out and returns Status::OK(). If
|
||||
* there is no field named "fieldName", stores defaultValue into *out and returns Status::OK().
|
||||
* If the field is found, but has non-numeric type, returns ErrorCodes::TypeMismatch. If the
|
||||
* value has numeric type, but cannot be represented as a 64-bit integer, returns
|
||||
* ErrorCodes::BadValue.
|
||||
*/
|
||||
Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
long long* out);
|
||||
StatusWith<long long> bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue);
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object" that represents a double-precision floating point
|
||||
@ -98,6 +138,7 @@ Status bsonExtractIntegerField(const BSONObj& object, StringData fieldName, long
|
||||
* For return values other than Status::OK(), the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractDoubleField(const BSONObj& object, StringData fieldName, double* out);
|
||||
StatusWith<double> bsonExtractDoubleField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* Finds a string-typed element named "fieldName" in "object" and stores its value in "out".
|
||||
@ -108,75 +149,9 @@ Status bsonExtractDoubleField(const BSONObj& object, StringData fieldName, doubl
|
||||
* Status::OK(), the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractStringField(const BSONObj& object, StringData fieldName, std::string* out);
|
||||
StatusWith<std::string> bsonExtractStringField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* Finds an Timestamp-typed element named "fieldName" in "object" and stores its value in "out".
|
||||
*
|
||||
* Returns Status::OK() and sets *out to the found element's Timestamp value on success. Returns
|
||||
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and ErrorCodes::TypeMismatch
|
||||
* if the type of the matching element is not Timestamp. For return values other than
|
||||
* Status::OK(), the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractTimestampField(const BSONObj& object, StringData fieldName, Timestamp* out);
|
||||
|
||||
/**
|
||||
* Finds an OID-typed element named "fieldName" in "object" and stores its value in "out".
|
||||
*
|
||||
* Returns Status::OK() and sets *out to the found element's OID value on success. Returns
|
||||
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and ErrorCodes::TypeMismatch
|
||||
* if the type of the matching element is not OID. For return values other than Status::OK(),
|
||||
* the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractOIDField(const BSONObj& object, StringData fieldName, OID* out);
|
||||
|
||||
/**
|
||||
* Finds a bool-like element named "fieldName" in "object".
|
||||
*
|
||||
* If a field named "fieldName" is present, and is either a number or boolean type, stores the
|
||||
* truth value of the field into "*out". If no field named "fieldName" is present, sets "*out"
|
||||
* to "defaultValue". In these cases, returns Status::OK().
|
||||
*
|
||||
* If "fieldName" is present more than once, behavior is undefined. If the found field is not a
|
||||
* boolean or number, returns ErrorCodes::TypeMismatch.
|
||||
*/
|
||||
Status bsonExtractBooleanFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
bool defaultValue,
|
||||
bool* out);
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object" that represents an integral value.
|
||||
*
|
||||
* If a field named "fieldName" is present and is a value of numeric type with an exact 64-bit
|
||||
* integer representation, returns that representation in *out and returns Status::OK(). If
|
||||
* there is no field named "fieldName", stores defaultValue into *out and returns Status::OK().
|
||||
* If the field is found, but has non-numeric type, returns ErrorCodes::TypeMismatch. If the
|
||||
* value has numeric type, but cannot be represented as a 64-bit integer, returns
|
||||
* ErrorCodes::BadValue.
|
||||
*/
|
||||
Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
long long* out);
|
||||
|
||||
/**
|
||||
* Finds a double-precision floating point element named "fieldName" in "object".
|
||||
*
|
||||
* If a field named "fieldName" is present, and is a double, stores the value of the field into
|
||||
* "*out". If no field named fieldName is present, sets "*out" to "defaultValue". In these cases,
|
||||
* returns Status::OK().
|
||||
*
|
||||
* If "fieldName" is present more than once, behavior is undefined. If the found field is not a
|
||||
* double, returns ErrorCodes::TypeMismatch.
|
||||
*/
|
||||
Status bsonExtractDoubleFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
double defaultValue,
|
||||
double* out);
|
||||
|
||||
/**
|
||||
* Finds a std::string element named "fieldName" in "object".
|
||||
*
|
||||
* If a field named "fieldName" is present, and is a string, stores the value of the field into
|
||||
* "*out". If no field named fieldName is present, sets "*out" to "defaultValue". In these
|
||||
* cases, returns Status::OK().
|
||||
@ -188,42 +163,29 @@ Status bsonExtractStringFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
StringData defaultValue,
|
||||
std::string* out);
|
||||
StatusWith<std::string> bsonExtractStringFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
StringData defaultValue);
|
||||
|
||||
/**
|
||||
* Finds an OID-typed element named "fieldName" in "object" and stores its value in *out.
|
||||
* Finds an Timestamp-typed element named "fieldName" in "object" and stores its value in "out".
|
||||
*
|
||||
* Returns Status::OK() and sets *out to the found element's OID value on success. If no field
|
||||
* named "fieldName" is present, *out is set to "defaultValue" and Status::OK() is returned.
|
||||
* Returns ErrorCodes::TypeMismatch if the type of the matching element is not OID. For return
|
||||
* values other than Status::OK(), the resulting value of *out is undefined.
|
||||
* Returns Status::OK() and sets *out to the found element's Timestamp value on success. Returns
|
||||
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and ErrorCodes::TypeMismatch
|
||||
* if the type of the matching element is not Timestamp. For return values other than
|
||||
* Status::OK(), the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractOIDFieldWithDefault(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
const OID& defaultValue,
|
||||
OID* out);
|
||||
Status bsonExtractTimestampField(const BSONObj& object, StringData fieldName, Timestamp* out);
|
||||
StatusWith<Timestamp> bsonExtractTimestampField(const BSONObj& object, StringData fieldName);
|
||||
|
||||
/**
|
||||
* Finds an element named "fieldName" in "object" that represents an integral value for which
|
||||
* 'pred' is true.
|
||||
* Finds an OID-typed element named "fieldName" in "object" and stores its value in "out".
|
||||
*
|
||||
* If a field named "fieldName" is present and is a value of numeric type with an exact 64-bit
|
||||
* integer representation, returns that representation in *out and returns Status::OK().
|
||||
* If there is no field named "fieldName", stores defaultValue into *out and returns Status::OK().
|
||||
* If the field is found, but has non-numeric type, returns ErrorCodes::TypeMismatch.
|
||||
* If the value has numeric type, but cannot be represented as a 64-bit integer, returns BadValue.
|
||||
* If the parsed value (or default) fails the predicate, returns ErrorCodes::BadValue.
|
||||
* Returns Status::OK() and sets *out to the found element's OID value on success. Returns
|
||||
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and ErrorCodes::TypeMismatch
|
||||
* if the type of the matching element is not OID. For return values other than Status::OK(),
|
||||
* the resulting value of "*out" is undefined.
|
||||
*/
|
||||
Status bsonExtractIntegerFieldWithDefaultIf(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
std::function<bool(long long)> pred,
|
||||
const std::string& predDescription,
|
||||
long long* out);
|
||||
|
||||
Status bsonExtractIntegerFieldWithDefaultIf(const BSONObj& object,
|
||||
StringData fieldName,
|
||||
long long defaultValue,
|
||||
std::function<bool(long long)> pred,
|
||||
long long* out);
|
||||
|
||||
Status bsonExtractOIDField(const BSONObj& object, StringData fieldName, OID* out);
|
||||
StatusWith<OID> bsonExtractOIDField(const BSONObj& object, StringData fieldName);
|
||||
} // namespace mongo
|
||||
|
||||
@ -147,48 +147,4 @@ TEST(ExtractBSON, ExtractIntegerField) {
|
||||
ASSERT_EQUALS(-(1LL << 55), v);
|
||||
ASSERT_OK(bsonExtractIntegerField(BSON("a" << 5178), "a", &v));
|
||||
ASSERT_EQUALS(5178, v);
|
||||
auto pred = [](long long x) {
|
||||
return x > 0;
|
||||
};
|
||||
ASSERT_OK(bsonExtractIntegerFieldWithDefaultIf(BSON("a" << 1), "a", -1LL, pred, &v));
|
||||
ASSERT_OK(bsonExtractIntegerFieldWithDefaultIf(BSON("a" << 1), "b", 1LL, pred, &v));
|
||||
auto msg = "'a' has to be greater than zero";
|
||||
auto status = bsonExtractIntegerFieldWithDefaultIf(BSON("a" << -1), "a", 1LL, pred, msg, &v);
|
||||
ASSERT_EQUALS(ErrorCodes::BadValue, status);
|
||||
ASSERT_STRING_CONTAINS(status.reason(), msg);
|
||||
ASSERT_EQUALS(ErrorCodes::BadValue,
|
||||
bsonExtractIntegerFieldWithDefaultIf(BSON("a" << 1), "b", -1LL, pred, &v));
|
||||
}
|
||||
|
||||
TEST(ExtractBSON, ExtractDoubleFieldWithDefault) {
|
||||
double d;
|
||||
ASSERT_EQUALS(ErrorCodes::NoSuchKey, bsonExtractDoubleField(BSON("a" << 1), "b", &d));
|
||||
ASSERT_OK(bsonExtractDoubleFieldWithDefault(BSON("a" << 1), "b", 1.2, &d));
|
||||
ASSERT_EQUALS(ErrorCodes::TypeMismatch, bsonExtractDoubleField(BSON("a" << false), "a", &d));
|
||||
ASSERT_OK(bsonExtractDoubleField(BSON("a" << 5178.0), "a", &d));
|
||||
ASSERT_EQUALS(5178.0, d);
|
||||
ASSERT_OK(bsonExtractDoubleField(BSON("a" << 5178), "a", &d));
|
||||
ASSERT_EQUALS(5178, d);
|
||||
ASSERT_OK(bsonExtractDoubleField(BSON("a" << 5178), "a", &d));
|
||||
ASSERT_EQUALS(5178.0, d);
|
||||
ASSERT_OK(bsonExtractDoubleField(BSON("a" << 5178.0), "a", &d));
|
||||
ASSERT_EQUALS(5178, d);
|
||||
ASSERT_OK(bsonExtractDoubleFieldWithDefault(BSON("a" << 1.0), "b", 1, &d));
|
||||
ASSERT_EQUALS(1.0, d);
|
||||
ASSERT_OK(bsonExtractDoubleFieldWithDefault(BSON("a" << 2.0), "a", 1, &d));
|
||||
ASSERT_EQUALS(2.0, d);
|
||||
}
|
||||
|
||||
TEST(ExtractBSON, ExtractOIDFieldWithDefault) {
|
||||
OID r;
|
||||
OID def = OID();
|
||||
ASSERT_EQUALS(ErrorCodes::NoSuchKey, bsonExtractOIDField(BSON("a" << 1), "b", &r));
|
||||
ASSERT_OK(bsonExtractOIDFieldWithDefault(BSON("a" << 2), "b", def, &r));
|
||||
ASSERT_EQUALS(ErrorCodes::TypeMismatch, bsonExtractOIDField(BSON("a" << false), "a", &r));
|
||||
ASSERT_OK(bsonExtractOIDField(BSON("a" << def), "a", &r));
|
||||
ASSERT_EQUALS(def, r);
|
||||
ASSERT_OK(bsonExtractOIDFieldWithDefault(BSON("a" << 3.0), "b", def, &r));
|
||||
ASSERT_EQUALS(def, r);
|
||||
ASSERT_OK(bsonExtractOIDFieldWithDefault(BSON("a" << def), "a", OID(), &r));
|
||||
ASSERT_EQUALS(def, r);
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/bson/bsonobjbuilder.h"
|
||||
#include "mongo/bson/bsontypes.h"
|
||||
#include "mongo/bson/util/bson_check.h"
|
||||
#include "mongo/bson/util/bson_extract.h"
|
||||
#include "mongo/db/auth/authorization_session.h" // IWYU pragma: keep
|
||||
#include "mongo/db/commands.h"
|
||||
@ -80,7 +79,7 @@ bool checkCOperationType(const BSONObj& opObj, const StringData opName) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns kNeedsSuperuser, if the provided applyOps command contains an empty applyOps command or
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include "mongo/base/error_codes.h"
|
||||
#include "mongo/base/string_data.h"
|
||||
#include "mongo/bson/bsontypes.h"
|
||||
#include "mongo/bson/util/bson_check.h"
|
||||
#include "mongo/db/auth/action_set.h"
|
||||
#include "mongo/db/auth/action_type.h"
|
||||
#include "mongo/db/auth/authorization_checks.h"
|
||||
@ -63,8 +62,19 @@
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/none.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
void checkBSONType(BSONType type, const BSONElement& elem) {
|
||||
uassert(elem.type() == BSONType::eoo ? ErrorCodes::NoSuchKey : ErrorCodes::TypeMismatch,
|
||||
fmt::format("Wrong type for {:?}. Expected a {}, got a {}.",
|
||||
elem.fieldNameStringData(),
|
||||
typeName(type),
|
||||
typeName(elem.type())),
|
||||
elem.type() == type);
|
||||
}
|
||||
|
||||
UUID OplogApplicationChecks::getUUIDFromOplogEntry(const BSONObj& oplogEntry) {
|
||||
BSONElement uiElem = oplogEntry["ui"];
|
||||
return uassertStatusOK(UUID::parse(uiElem));
|
||||
|
||||
@ -31,14 +31,15 @@
|
||||
#include "mongo/bson/bsonelement.h"
|
||||
#include "mongo/bson/bsonobj.h"
|
||||
#include "mongo/db/auth/authorization_session.h"
|
||||
#include "mongo/db/database_name.h"
|
||||
#include "mongo/db/operation_context.h"
|
||||
#include "mongo/util/modules.h"
|
||||
#include "mongo/util/uuid.h"
|
||||
|
||||
namespace mongo {
|
||||
class BSONElement;
|
||||
class BSONObj;
|
||||
class DatabaseName;
|
||||
class OperationContext;
|
||||
|
||||
/** `uassert` that `elem` type matches the specified `type`. */
|
||||
void checkBSONType(BSONType type, const BSONElement& elem);
|
||||
|
||||
// OplogApplicationValidity represents special conditions relevant to authorization for
|
||||
// oplog application.
|
||||
|
||||
@ -102,9 +102,15 @@ StatusWith<ReplSetMetadata> ReplSetMetadata::readFromMetadata(const BSONObj& met
|
||||
return status;
|
||||
|
||||
OID id;
|
||||
status = bsonExtractOIDFieldWithDefault(replMetadataObj, kReplicaSetIdFieldName, OID(), &id);
|
||||
if (!status.isOK())
|
||||
return status;
|
||||
if (BSONElement e = replMetadataObj.getField(kReplicaSetIdFieldName); !e.eoo()) {
|
||||
if (e.type() != BSONType::oid)
|
||||
return Status(ErrorCodes::TypeMismatch,
|
||||
fmt::format("{:?} had the wrong type. Expected {}, found {}",
|
||||
kReplicaSetIdFieldName,
|
||||
BSONType::oid,
|
||||
typeName(e.type())));
|
||||
id = e.OID();
|
||||
}
|
||||
|
||||
// We provide a default because these fields will be removed in SERVER-27668.
|
||||
long long primaryIndex;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user