summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher/doc_validation_error.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/matcher/doc_validation_error.cpp')
-rw-r--r--src/mongo/db/matcher/doc_validation_error.cpp103
1 files changed, 88 insertions, 15 deletions
diff --git a/src/mongo/db/matcher/doc_validation_error.cpp b/src/mongo/db/matcher/doc_validation_error.cpp
index bbc2f4eb1cb..0175172f3b5 100644
--- a/src/mongo/db/matcher/doc_validation_error.cpp
+++ b/src/mongo/db/matcher/doc_validation_error.cpp
@@ -44,7 +44,11 @@
#include "mongo/db/matcher/expression_type.h"
#include "mongo/db/matcher/expression_visitor.h"
#include "mongo/db/matcher/match_expression_walker.h"
+#include "mongo/db/matcher/schema/expression_internal_schema_fmod.h"
+#include "mongo/db/matcher/schema/expression_internal_schema_max_length.h"
+#include "mongo/db/matcher/schema/expression_internal_schema_min_length.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
+#include "mongo/db/matcher/schema/expression_internal_schema_str_length.h"
namespace mongo::doc_validation_error {
namespace {
@@ -356,17 +360,65 @@ public:
void visit(const InternalExprEqMatchExpression* expr) final {}
void visit(const InternalSchemaAllElemMatchFromIndexMatchExpression* expr) final {}
void visit(const InternalSchemaAllowedPropertiesMatchExpression* expr) final {}
- void visit(const InternalSchemaBinDataEncryptedTypeExpression* expr) final {}
- void visit(const InternalSchemaBinDataSubTypeExpression* expr) final {}
+ void visit(const InternalSchemaBinDataEncryptedTypeExpression* expr) final {
+ static constexpr auto kNormalReason = "encrypted value has wrong type";
+ _context->pushNewFrame(*expr, _context->getCurrentDocument());
+ if (_context->shouldGenerateError(*expr)) {
+ ElementPath path(expr->path(), LeafArrayBehavior::kNoTraversal);
+ BSONMatchableDocument doc(_context->getCurrentDocument());
+ MatchableDocument::IteratorHolder cursor(&doc, &path);
+ invariant(cursor->more());
+ auto elem = cursor->next().element();
+ // Only generate an error in the normal case since if the value exists and it is
+ // encrypted, in the inverted case, this node's sibling expression will generate an
+ // appropriate error.
+ if (elem.type() == BSONType::BinData && elem.binDataType() == BinDataType::Encrypt &&
+ _context->inversion == InvertError::kNormal) {
+ auto& builder = _context->getCurrentObjBuilder();
+ appendOperatorName(*expr->getErrorAnnotation(), &builder);
+ builder.append("reason", kNormalReason);
+ } else {
+ _context->setCurrentRuntimeState(RuntimeState::kNoError);
+ }
+ }
+ }
+ void visit(const InternalSchemaBinDataSubTypeExpression* expr) final {
+ static constexpr auto kNormalReason = "value was not encrypted";
+ static constexpr auto kInvertedReason = "value was encrypted";
+ _context->pushNewFrame(*expr, _context->getCurrentDocument());
+ if (_context->shouldGenerateError(*expr)) {
+ auto& builder = _context->getCurrentObjBuilder();
+ appendOperatorName(*expr->getErrorAnnotation(), &builder);
+ appendErrorReason(*expr, kNormalReason, kInvertedReason);
+ }
+ }
void visit(const InternalSchemaCondMatchExpression* expr) final {}
void visit(const InternalSchemaEqMatchExpression* expr) final {}
- void visit(const InternalSchemaFmodMatchExpression* expr) final {}
+ void visit(const InternalSchemaFmodMatchExpression* expr) final {
+ static constexpr auto kNormalReason =
+ "considered value is not a multiple of the specified value";
+ static constexpr auto kInvertedReason =
+ "considered value is a multiple of the specified value";
+ static const std::set<BSONType> kExpectedTypes{BSONType::NumberLong,
+ BSONType::NumberDouble,
+ BSONType::NumberDecimal,
+ BSONType::NumberInt};
+ generatePathError(*expr,
+ kNormalReason,
+ kInvertedReason,
+ &kExpectedTypes,
+ LeafArrayBehavior::kNoTraversal);
+ }
void visit(const InternalSchemaMatchArrayIndexMatchExpression* expr) final {}
void visit(const InternalSchemaMaxItemsMatchExpression* expr) final {}
- void visit(const InternalSchemaMaxLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMaxLengthMatchExpression* expr) final {
+ generateStringLengthError(*expr);
+ }
void visit(const InternalSchemaMaxPropertiesMatchExpression* expr) final {}
void visit(const InternalSchemaMinItemsMatchExpression* expr) final {}
- void visit(const InternalSchemaMinLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMinLengthMatchExpression* expr) final {
+ generateStringLengthError(*expr);
+ }
void visit(const InternalSchemaMinPropertiesMatchExpression* expr) final {}
void visit(const InternalSchemaObjectMatchExpression* expr) final {
// This node should never be responsible for generating an error directly.
@@ -414,9 +466,11 @@ public:
void visit(const ModMatchExpression* expr) final {
static constexpr auto kNormalReason = "$mod did not evaluate to expected remainder";
static constexpr auto kInvertedReason = "$mod did evaluate to expected remainder";
- static const std::set<BSONType> expectedTypes{
- NumberLong, NumberDouble, NumberDecimal, NumberInt};
- generatePathError(*expr, kNormalReason, kInvertedReason, &expectedTypes);
+ static const std::set<BSONType> kExpectedTypes{BSONType::NumberLong,
+ BSONType::NumberDouble,
+ BSONType::NumberDecimal,
+ BSONType::NumberInt};
+ generatePathError(*expr, kNormalReason, kInvertedReason, &kExpectedTypes);
}
void visit(const NorMatchExpression* expr) final {
preVisitTreeOperator(expr);
@@ -442,8 +496,9 @@ public:
void visit(const RegexMatchExpression* expr) final {
static constexpr auto kNormalReason = "regular expression did not match";
static constexpr auto kInvertedReason = "regular expression did match";
- static const std::set<BSONType> expectedTypes{String, Symbol, RegEx};
- generatePathError(*expr, kNormalReason, kInvertedReason, &expectedTypes);
+ static const std::set<BSONType> kExpectedTypes{
+ BSONType::String, BSONType::Symbol, BSONType::RegEx};
+ generatePathError(*expr, kNormalReason, kInvertedReason, &kExpectedTypes);
}
void visit(const SizeMatchExpression* expr) final {
static constexpr auto kNormalReason = "array length was not equal to given size";
@@ -713,6 +768,14 @@ private:
}
}
+ void generateStringLengthError(const InternalSchemaStrLengthMatchExpression& expr) {
+ static constexpr auto kNormalReason = "specified string length was not satisfied";
+ static constexpr auto kInvertedReason = "specified string length was satisfied";
+ static const std::set<BSONType> expectedTypes{BSONType::String};
+ generatePathError(
+ expr, kNormalReason, kInvertedReason, &expectedTypes, LeafArrayBehavior::kNoTraversal);
+ }
+
ValidationErrorContext* _context;
};
@@ -873,17 +936,27 @@ public:
void visit(const InternalExprEqMatchExpression* expr) final {}
void visit(const InternalSchemaAllElemMatchFromIndexMatchExpression* expr) final {}
void visit(const InternalSchemaAllowedPropertiesMatchExpression* expr) final {}
- void visit(const InternalSchemaBinDataEncryptedTypeExpression* expr) final {}
- void visit(const InternalSchemaBinDataSubTypeExpression* expr) final {}
+ void visit(const InternalSchemaBinDataEncryptedTypeExpression* expr) final {
+ _context->finishCurrentError(expr);
+ }
+ void visit(const InternalSchemaBinDataSubTypeExpression* expr) final {
+ _context->finishCurrentError(expr);
+ }
void visit(const InternalSchemaCondMatchExpression* expr) final {}
void visit(const InternalSchemaEqMatchExpression* expr) final {}
- void visit(const InternalSchemaFmodMatchExpression* expr) final {}
+ void visit(const InternalSchemaFmodMatchExpression* expr) final {
+ _context->finishCurrentError(expr);
+ }
void visit(const InternalSchemaMatchArrayIndexMatchExpression* expr) final {}
void visit(const InternalSchemaMaxItemsMatchExpression* expr) final {}
- void visit(const InternalSchemaMaxLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMaxLengthMatchExpression* expr) final {
+ _context->finishCurrentError(expr);
+ }
void visit(const InternalSchemaMaxPropertiesMatchExpression* expr) final {}
void visit(const InternalSchemaMinItemsMatchExpression* expr) final {}
- void visit(const InternalSchemaMinLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMinLengthMatchExpression* expr) final {
+ _context->finishCurrentError(expr);
+ }
void visit(const InternalSchemaMinPropertiesMatchExpression* expr) final {}
void visit(const InternalSchemaObjectMatchExpression* expr) final {
_context->finishCurrentError(expr);