diff options
author | George Wangensteen <george.wangensteen@mongodb.com> | 2020-09-10 21:05:01 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-25 17:07:52 +0000 |
commit | 8e53f9b4db4f3cc2c09e6a3fa2c29781142eb896 (patch) | |
tree | a10e791944505fc8137df9bebef3dfa334d771e1 /src/mongo/db/cst/c_node_validation.cpp | |
parent | 0bc3808a2be9ab03f5ea06673a4152bda856010d (diff) | |
download | mongo-8e53f9b4db4f3cc2c09e6a3fa2c29781142eb896.tar.gz |
SERVER-48850 Implement element and $comment operators in CST
Diffstat (limited to 'src/mongo/db/cst/c_node_validation.cpp')
-rw-r--r-- | src/mongo/db/cst/c_node_validation.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/mongo/db/cst/c_node_validation.cpp b/src/mongo/db/cst/c_node_validation.cpp index a6343b22d56..802f9597cd9 100644 --- a/src/mongo/db/cst/c_node_validation.cpp +++ b/src/mongo/db/cst/c_node_validation.cpp @@ -34,8 +34,10 @@ #include "mongo/base/status.h" #include "mongo/bson/bson_depth.h" +#include "mongo/db/cst/c_node.h" #include "mongo/db/cst/c_node_validation.h" #include "mongo/db/cst/path.h" +#include "mongo/db/matcher/matcher_type_set.h" #include "mongo/db/pipeline/field_path.h" #include "mongo/db/pipeline/variable_validation.h" #include "mongo/db/query/util/make_data_structure.h" @@ -252,6 +254,55 @@ Status addPathsFromTreeToSet(const CNode::ObjectChildren& children, return Status::OK(); } +template <typename T> +Status validateNumericType(T num) { + auto valueAsInt = BSON("" << num).firstElement().parseIntegerElementToInt(); + if (!valueAsInt.isOK() || valueAsInt.getValue() == 0 || + !isValidBSONType(valueAsInt.getValue())) { + if constexpr (std::is_same_v<std::decay_t<T>, UserDecimal>) { + return Status{ErrorCodes::FailedToParse, + str::stream() << "invalid numerical type code: " << num.toString() + << " provided as argument"}; + } else { + return Status{ErrorCodes::FailedToParse, + str::stream() + << "invalid numerical type code: " << num << " provided as argument"}; + } + } + return Status::OK(); +} + +Status validateSingleType(const CNode& element) { + return stdx::visit( + visit_helper::Overloaded{ + [&](const UserDouble& dbl) { return validateNumericType(dbl); }, + [&](const UserInt& num) { return validateNumericType(num); }, + [&](const UserLong& lng) { return validateNumericType(lng); }, + [&](const UserDecimal& dc) { return validateNumericType(dc); }, + [&](const UserString& st) { + if (st == MatcherTypeSet::kMatchesAllNumbersAlias) { + return Status::OK(); + } + auto optValue = findBSONTypeAlias(st); + if (!optValue) { + // The string "missing" can be returned from the $type agg expression, but is + // not valid for use in the $type match expression predicate. Return a special + // error message for this case. + if (st == StringData{typeName(BSONType::EOO)}) { + return Status{ + ErrorCodes::FailedToParse, + "unknown type name alias 'missing' (to query for " + "non-existence of a field, use {$exists:false}) provided as argument"}; + } + return Status{ErrorCodes::FailedToParse, + str::stream() << "unknown type name alias: '" << st + << "' provided as argument"}; + } + return Status::OK(); + }, + [&](auto &&) -> Status { MONGO_UNREACHABLE; }}, + element.payload); +} } // namespace StatusWith<IsInclusion> validateProjectionAsInclusionOrExclusion(const CNode& projects) { @@ -326,4 +377,16 @@ Status validateSortPath(const std::vector<std::string>& pathComponents) { return Status::OK(); } +Status validateTypeOperatorArgument(const CNode& types) { + // If the CNode is an array, we need to validate all of the types within it. + if (auto&& children = stdx::get_if<CNode::ArrayChildren>(&types.payload)) { + for (auto&& child : (*children)) { + if (auto status = validateSingleType(child); !status.isOK()) { + return status; + } + } + return Status::OK(); + } + return validateSingleType(types); +} } // namespace mongo::c_node_validation |