summaryrefslogtreecommitdiff
path: root/src/mongo/db/cst/c_node_validation.cpp
diff options
context:
space:
mode:
authorGeorge Wangensteen <george.wangensteen@mongodb.com>2020-09-10 21:05:01 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-09-25 17:07:52 +0000
commit8e53f9b4db4f3cc2c09e6a3fa2c29781142eb896 (patch)
treea10e791944505fc8137df9bebef3dfa334d771e1 /src/mongo/db/cst/c_node_validation.cpp
parent0bc3808a2be9ab03f5ea06673a4152bda856010d (diff)
downloadmongo-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.cpp63
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