diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/exec/and_common.h (renamed from src/mongo/db/exec/and_common-inl.h) | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/and_hash.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/and_sorted.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/field_parser-inl.h | 364 | ||||
-rw-r--r-- | src/mongo/db/field_parser.h | 312 |
5 files changed, 313 insertions, 369 deletions
diff --git a/src/mongo/db/exec/and_common-inl.h b/src/mongo/db/exec/and_common.h index e44918f480b..beb84e5751f 100644 --- a/src/mongo/db/exec/and_common-inl.h +++ b/src/mongo/db/exec/and_common.h @@ -27,6 +27,8 @@ * it in the license file. */ +#pragma once + #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/db/exec/working_set.h" diff --git a/src/mongo/db/exec/and_hash.cpp b/src/mongo/db/exec/and_hash.cpp index 76427fe126f..dc8197afc8e 100644 --- a/src/mongo/db/exec/and_hash.cpp +++ b/src/mongo/db/exec/and_hash.cpp @@ -29,7 +29,7 @@ #include "mongo/db/exec/and_hash.h" -#include "mongo/db/exec/and_common-inl.h" +#include "mongo/db/exec/and_common.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set.h" #include "mongo/db/exec/working_set_common.h" diff --git a/src/mongo/db/exec/and_sorted.cpp b/src/mongo/db/exec/and_sorted.cpp index 31c7426f8d9..cdb095ba08d 100644 --- a/src/mongo/db/exec/and_sorted.cpp +++ b/src/mongo/db/exec/and_sorted.cpp @@ -29,7 +29,7 @@ #include "mongo/db/exec/and_sorted.h" -#include "mongo/db/exec/and_common-inl.h" +#include "mongo/db/exec/and_common.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/stdx/memory.h" diff --git a/src/mongo/db/field_parser-inl.h b/src/mongo/db/field_parser-inl.h deleted file mode 100644 index 3ad18fad184..00000000000 --- a/src/mongo/db/field_parser-inl.h +++ /dev/null @@ -1,364 +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/db/field_parser.h" -#include "mongo/util/str.h" - -namespace mongo { -namespace { - -template <class T> -void _genFieldErrMsg(const BSONElement& elem, - const BSONField<T>& field, - const std::string expected, - std::string* errMsg) { - if (!errMsg) - return; - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " << expected - << ", found " << elem.toString(); -} - -template <typename T> -void _clearOwnedVector(std::vector<T*>* vec) { - for (typename std::vector<T*>::iterator it = vec->begin(); it != vec->end(); ++it) { - delete (*it); - } -} - -} // namespace - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<T>& field, - T* out, - std::string* errMsg) { - BSONElement elem = doc[field.name()]; - if (elem.eoo()) { - if (field.hasDefault()) { - field.getDefault().cloneTo(out); - return FIELD_DEFAULT; - } else { - return FIELD_NONE; - } - } - - if (elem.type() != Object && elem.type() != Array) { - _genFieldErrMsg(elem, field, "Object/Array", errMsg); - return FIELD_INVALID; - } - - if (!out->parseBSON(elem.embeddedObject(), errMsg)) { - return FIELD_INVALID; - } - - return FIELD_SET; -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<T*>& field, - T** out, - std::string* errMsg) { - BSONElement elem = doc[field.name()]; - if (elem.eoo()) { - if (field.hasDefault()) { - std::unique_ptr<T> temp(new T); - field.getDefault()->cloneTo(temp.get()); - - *out = temp.release(); - return FIELD_DEFAULT; - } else { - return FIELD_NONE; - } - } - - if (elem.type() != Object && elem.type() != Array) { - _genFieldErrMsg(elem, field, "Object/Array", errMsg); - return FIELD_INVALID; - } - - std::unique_ptr<T> temp(new T); - if (!temp->parseBSON(elem.embeddedObject(), errMsg)) { - return FIELD_INVALID; - } - - *out = temp.release(); - return FIELD_SET; -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<T>& field, - T** out, - std::string* errMsg) { - BSONElement elem = doc[field.name()]; - if (elem.eoo()) { - if (field.hasDefault()) { - *out = new T; - field.getDefault().cloneTo(*out); - return FIELD_DEFAULT; - } else { - return FIELD_NONE; - } - } - - if (elem.type() != Object && elem.type() != Array) { - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " - << "vector or array" - << ", found " << doc[field.name()].toString(); - } - return FIELD_INVALID; - } - - std::unique_ptr<T> temp(new T); - if (!temp->parseBSON(elem.embeddedObject(), errMsg)) { - return FIELD_INVALID; - } - - *out = temp.release(); - return FIELD_SET; -} - -// Extracts an array into a vector -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<std::vector<T>>& field, - std::vector<T>* out, - std::string* errMsg) { - return extract(doc[field.name()], field, out, errMsg); -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONElement elem, - const BSONField<std::vector<T>>& field, - std::vector<T>* out, - std::string* errMsg) { - if (elem.eoo()) { - if (field.hasDefault()) { - *out = field.getDefault(); - return FIELD_DEFAULT; - } else { - return FIELD_NONE; - } - } - - if (elem.type() == Array) { - BSONArray arr = BSONArray(elem.embeddedObject()); - std::string elErrMsg; - - // Append all the new elements to the end of the vector - size_t initialSize = out->size(); - out->resize(initialSize + arr.nFields()); - - int i = 0; - BSONObjIterator objIt(arr); - while (objIt.more()) { - BSONElement next = objIt.next(); - BSONField<T> fieldFor(next.fieldName(), out->at(initialSize + i)); - - if (!FieldParser::extract(next, fieldFor, &out->at(initialSize + i), &elErrMsg)) { - if (errMsg) { - *errMsg = str::stream() << "error parsing element " << i << " of field " - << field() << causedBy(elErrMsg); - } - return FIELD_INVALID; - } - i++; - } - - return FIELD_SET; - } - - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " - << "vector array" - << ", found " << elem.toString(); - } - return FIELD_INVALID; -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<std::vector<T*>>& field, - std::vector<T*>* out, - std::string* errMsg) { - dassert(!field.hasDefault()); - - BSONElement elem = doc[field.name()]; - if (elem.eoo()) { - return FIELD_NONE; - } - - return extract(elem, field, out, errMsg); -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONElement elem, - const BSONField<std::vector<T*>>& field, - std::vector<T*>* out, - std::string* errMsg) { - if (elem.type() != Array) { - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " - << "vector array" - << ", found " << elem.toString(); - } - return FIELD_INVALID; - } - - BSONArray arr = BSONArray(elem.embeddedObject()); - BSONObjIterator objIt(arr); - while (objIt.more()) { - BSONElement next = objIt.next(); - - if (next.type() != Object) { - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field contents, " - << "expected object, found " << elem.type(); - } - return FIELD_INVALID; - } - - std::unique_ptr<T> toInsert(new T); - - if (!toInsert->parseBSON(next.embeddedObject(), errMsg)) { - return FIELD_INVALID; - } - - out->push_back(toInsert.release()); - } - - return FIELD_SET; -} - -template <typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<std::vector<T*>>& field, - std::vector<T*>** out, - std::string* errMsg) { - dassert(!field.hasDefault()); - - BSONElement elem = doc[field.name()]; - if (elem.eoo()) { - return FIELD_NONE; - } - - if (elem.type() != Array) { - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " - << "vector array" - << ", found " << doc[field.name()].toString(); - } - return FIELD_INVALID; - } - - std::unique_ptr<std::vector<T*>> tempVector(new std::vector<T*>); - - BSONArray arr = BSONArray(elem.embeddedObject()); - BSONObjIterator objIt(arr); - while (objIt.more()) { - BSONElement next = objIt.next(); - - if (next.type() != Object) { - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field contents, " - << "expected object, found " << elem.type(); - } - _clearOwnedVector(tempVector.get()); - return FIELD_INVALID; - } - - std::unique_ptr<T> toInsert(new T); - if (!toInsert->parseBSON(next.embeddedObject(), errMsg)) { - _clearOwnedVector(tempVector.get()); - return FIELD_INVALID; - } - - tempVector->push_back(toInsert.release()); - } - - *out = tempVector.release(); - return FIELD_SET; -} - -// Extracts an object into a map -template <typename K, typename T> -FieldParser::FieldState FieldParser::extract(BSONObj doc, - const BSONField<std::map<K, T>>& field, - std::map<K, T>* out, - std::string* errMsg) { - return extract(doc[field.name()], field, out, errMsg); -} - -template <typename K, typename T> -FieldParser::FieldState FieldParser::extract(BSONElement elem, - const BSONField<std::map<K, T>>& field, - std::map<K, T>* out, - std::string* errMsg) { - if (elem.eoo()) { - if (field.hasDefault()) { - *out = field.getDefault(); - return FIELD_DEFAULT; - } else { - return FIELD_NONE; - } - } - - if (elem.type() == Object) { - BSONObj obj = elem.embeddedObject(); - std::string elErrMsg; - - BSONObjIterator objIt(obj); - while (objIt.more()) { - BSONElement next = objIt.next(); - T& value = (*out)[next.fieldName()]; - - BSONField<T> fieldFor(next.fieldName(), value); - if (!FieldParser::extract(next, fieldFor, &value, &elErrMsg)) { - if (errMsg) { - *errMsg = str::stream() << "error parsing map element " << next.fieldName() - << " of field " << field() << causedBy(elErrMsg); - } - return FIELD_INVALID; - } - } - - return FIELD_SET; - } - - if (errMsg) { - *errMsg = str::stream() << "wrong type for '" << field() << "' field, expected " - << "vector array" - << ", found " << elem.toString(); - } - return FIELD_INVALID; -} - -} // namespace mongo diff --git a/src/mongo/db/field_parser.h b/src/mongo/db/field_parser.h index 7ad0315efd3..748787affe9 100644 --- a/src/mongo/db/field_parser.h +++ b/src/mongo/db/field_parser.h @@ -29,14 +29,31 @@ #pragma once +#include <fmt/format.h> +#include <fmt/ostream.h> #include <string> +#include "mongo/base/string_data.h" #include "mongo/db/jsobj.h" +#include "mongo/util/scopeguard.h" #include "mongo/util/time_support.h" namespace mongo { class FieldParser { +private: + template <typename T> + static void _genFieldErrMsg(const BSONElement& elem, + const BSONField<T>& field, + StringData expected, + std::string* errMsg) { + using namespace fmt::literals; + if (!errMsg) + return; + *errMsg = "wrong type for '{}' field, expected {}, found {}"_format( + field(), expected, elem.toString()); + } + public: /** * Returns true and fills in 'out' with the contents of the field described by 'field' @@ -321,7 +338,296 @@ public: std::string* errMsg = NULL); }; -} // namespace mongo +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<T>& field, + T* out, + std::string* errMsg) { + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + if (field.hasDefault()) { + field.getDefault().cloneTo(out); + return FIELD_DEFAULT; + } else { + return FIELD_NONE; + } + } + + if (elem.type() != Object && elem.type() != Array) { + _genFieldErrMsg(elem, field, "Object/Array", errMsg); + return FIELD_INVALID; + } + + if (!out->parseBSON(elem.embeddedObject(), errMsg)) { + return FIELD_INVALID; + } + + return FIELD_SET; +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<T*>& field, + T** out, + std::string* errMsg) { + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + if (field.hasDefault()) { + std::unique_ptr<T> temp(new T); + field.getDefault()->cloneTo(temp.get()); + + *out = temp.release(); + return FIELD_DEFAULT; + } else { + return FIELD_NONE; + } + } + + if (elem.type() != Object && elem.type() != Array) { + _genFieldErrMsg(elem, field, "Object/Array", errMsg); + return FIELD_INVALID; + } + + std::unique_ptr<T> temp(new T); + if (!temp->parseBSON(elem.embeddedObject(), errMsg)) { + return FIELD_INVALID; + } + + *out = temp.release(); + return FIELD_SET; +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<T>& field, + T** out, + std::string* errMsg) { + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + if (field.hasDefault()) { + *out = new T; + field.getDefault().cloneTo(*out); + return FIELD_DEFAULT; + } else { + return FIELD_NONE; + } + } + + if (elem.type() != Object && elem.type() != Array) { + _genFieldErrMsg(elem, field(), "vector or array", errMsg); + return FIELD_INVALID; + } + + std::unique_ptr<T> temp(new T); + if (!temp->parseBSON(elem.embeddedObject(), errMsg)) { + return FIELD_INVALID; + } + + *out = temp.release(); + return FIELD_SET; +} + +// Extracts an array into a vector +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<std::vector<T>>& field, + std::vector<T>* out, + std::string* errMsg) { + return extract(doc[field.name()], field, out, errMsg); +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONElement elem, + const BSONField<std::vector<T>>& field, + std::vector<T>* out, + std::string* errMsg) { + using namespace fmt::literals; + if (elem.eoo()) { + if (field.hasDefault()) { + *out = field.getDefault(); + return FIELD_DEFAULT; + } else { + return FIELD_NONE; + } + } + + if (elem.type() == Array) { + BSONArray arr = BSONArray(elem.embeddedObject()); + std::string elErrMsg; + + // Append all the new elements to the end of the vector + size_t initialSize = out->size(); + out->resize(initialSize + arr.nFields()); + + int i = 0; + BSONObjIterator objIt(arr); + while (objIt.more()) { + BSONElement next = objIt.next(); + BSONField<T> fieldFor(next.fieldName(), out->at(initialSize + i)); + + if (!FieldParser::extract(next, fieldFor, &out->at(initialSize + i), &elErrMsg)) { + if (errMsg) { + *errMsg = "error parsing element {} of field {}{}"_format( + i, field(), causedBy(elErrMsg)); + } + return FIELD_INVALID; + } + i++; + } + + return FIELD_SET; + } + + _genFieldErrMsg(elem, field, "vector array", errMsg); + return FIELD_INVALID; +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<std::vector<T*>>& field, + std::vector<T*>* out, + std::string* errMsg) { + dassert(!field.hasDefault()); + + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + return FIELD_NONE; + } + + return extract(elem, field, out, errMsg); +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONElement elem, + const BSONField<std::vector<T*>>& field, + std::vector<T*>* out, + std::string* errMsg) { + if (elem.type() != Array) { + _genFieldErrMsg(elem, field, "vector array", errMsg); + return FIELD_INVALID; + } + + BSONArray arr = BSONArray(elem.embeddedObject()); + BSONObjIterator objIt(arr); + while (objIt.more()) { + BSONElement next = objIt.next(); + + if (next.type() != Object) { + _genFieldErrMsg(elem, field, "object", errMsg); + return FIELD_INVALID; + } + + std::unique_ptr<T> toInsert(new T); + + if (!toInsert->parseBSON(next.embeddedObject(), errMsg)) { + return FIELD_INVALID; + } + + out->push_back(toInsert.release()); + } + + return FIELD_SET; +} + +template <typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<std::vector<T*>>& field, + std::vector<T*>** out, + std::string* errMsg) { + using namespace fmt::literals; + dassert(!field.hasDefault()); + + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + return FIELD_NONE; + } + + if (elem.type() != Array) { + _genFieldErrMsg(elem, field, "vector array", errMsg); + return FIELD_INVALID; + } + + auto tempVector = std::make_unique<std::vector<T*>>(); + auto guard = makeGuard([&tempVector] { + if (tempVector) { + for (T*& raw : *tempVector) { + delete raw; + } + } + }); + + BSONArray arr = BSONArray(elem.embeddedObject()); + BSONObjIterator objIt(arr); + while (objIt.more()) { + BSONElement next = objIt.next(); + + if (next.type() != Object) { + if (errMsg) { + *errMsg = "wrong type for '{}' field contents, expected object, found {}"_format( + field(), elem.type()); + } + return FIELD_INVALID; + } + + std::unique_ptr<T> toInsert(new T); + if (!toInsert->parseBSON(next.embeddedObject(), errMsg)) { + return FIELD_INVALID; + } + + tempVector->push_back(toInsert.release()); + } + *out = tempVector.release(); + return FIELD_SET; +} + +// Extracts an object into a map +template <typename K, typename T> +FieldParser::FieldState FieldParser::extract(BSONObj doc, + const BSONField<std::map<K, T>>& field, + std::map<K, T>* out, + std::string* errMsg) { + return extract(doc[field.name()], field, out, errMsg); +} + +template <typename K, typename T> +FieldParser::FieldState FieldParser::extract(BSONElement elem, + const BSONField<std::map<K, T>>& field, + std::map<K, T>* out, + std::string* errMsg) { + using namespace fmt::literals; + if (elem.eoo()) { + if (field.hasDefault()) { + *out = field.getDefault(); + return FIELD_DEFAULT; + } else { + return FIELD_NONE; + } + } + + if (elem.type() == Object) { + BSONObj obj = elem.embeddedObject(); + std::string elErrMsg; + + BSONObjIterator objIt(obj); + while (objIt.more()) { + BSONElement next = objIt.next(); + T& value = (*out)[next.fieldName()]; + + BSONField<T> fieldFor(next.fieldName(), value); + if (!FieldParser::extract(next, fieldFor, &value, &elErrMsg)) { + if (errMsg) { + *errMsg = "error parsing map element {} of field {}{}"_format( + next.fieldName(), field(), causedBy(elErrMsg)); + } + return FIELD_INVALID; + } + } + + return FIELD_SET; + } + + _genFieldErrMsg(elem, field, "vector array", errMsg); + return FIELD_INVALID; +} -// Inline functions for templating -#include "field_parser-inl.h" +} // namespace mongo |