summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnne Lim <anne.lim@mongodb.com>2017-08-02 09:48:19 -0400
committerAnne Lim <anne.lim@mongodb.com>2017-08-02 09:48:19 -0400
commitb66d485345c99c8877f2d0bc72a4f123de720cb0 (patch)
tree31844a3949fd1c900b3f7e93929faea1671b0c9b /src
parent0deaa0f0ec0f659afcf39144e9dc0b60ec464ea8 (diff)
downloadmongo-b66d485345c99c8877f2d0bc72a4f123de720cb0.tar.gz
Revert "scalars part 2"
This reverts commit 0deaa0f0ec0f659afcf39144e9dc0b60ec464ea8.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/matcher/schema/json_schema_parser.cpp93
-rw-r--r--src/mongo/db/matcher/schema/json_schema_parser_test.cpp208
2 files changed, 46 insertions, 255 deletions
diff --git a/src/mongo/db/matcher/schema/json_schema_parser.cpp b/src/mongo/db/matcher/schema/json_schema_parser.cpp
index 591c1a8be60..4418eb2f699 100644
--- a/src/mongo/db/matcher/schema/json_schema_parser.cpp
+++ b/src/mongo/db/matcher/schema/json_schema_parser.cpp
@@ -33,8 +33,6 @@
#include "mongo/bson/bsontypes.h"
#include "mongo/db/matcher/expression_always_boolean.h"
#include "mongo/db/matcher/expression_parser.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/stdx/memory.h"
#include "mongo/util/string_map.h"
@@ -47,9 +45,6 @@ constexpr StringData kSchemaExclusiveMaximumKeyword = "exclusiveMaximum"_sd;
constexpr StringData kSchemaExclusiveMinimumKeyword = "exclusiveMinimum"_sd;
constexpr StringData kSchemaMaximumKeyword = "maximum"_sd;
constexpr StringData kSchemaMinimumKeyword = "minimum"_sd;
-constexpr StringData kSchemaMaxLengthKeyword = "maxLength"_sd;
-constexpr StringData kSchemaMinLengthKeyword = "minLength"_sd;
-constexpr StringData kSchemaPatternKeyword = "pattern"_sd;
constexpr StringData kSchemaPropertiesKeyword = "properties"_sd;
constexpr StringData kSchemaTypeKeyword = "type"_sd;
@@ -174,6 +169,7 @@ StatusWithMatchExpression parseMaximum(StringData path,
return status;
}
+ // We use Number as a stand-in for all numeric restrictions.
TypeMatchExpression::Type restrictionType;
restrictionType.allNumbers = true;
return makeRestriction(restrictionType, std::move(expr), typeExpr);
@@ -205,65 +201,11 @@ StatusWithMatchExpression parseMinimum(StringData path,
return status;
}
+ // We use Number as a stand-in for all numeric restrictions.
TypeMatchExpression::Type restrictionType;
restrictionType.allNumbers = true;
return makeRestriction(restrictionType, std::move(expr), typeExpr);
}
-
-template <class T>
-StatusWithMatchExpression parseStrLength(StringData path,
- BSONElement strLength,
- TypeMatchExpression* typeExpr,
- StringData keyword) {
- if (!strLength.isNumber()) {
- return {
- Status(ErrorCodes::TypeMismatch,
- str::stream() << "$jsonSchema keyword '" << keyword << "' must be a number")};
- }
-
- auto strLengthWithStatus =
- MatchExpressionParser::parseIntegerElementToNonNegativeLong(strLength);
-
- if (!strLengthWithStatus.isOK()) {
- return strLengthWithStatus.getStatus();
- }
-
- if (path.empty()) {
- return {stdx::make_unique<AlwaysTrueMatchExpression>()};
- }
-
- auto expr = stdx::make_unique<T>();
- auto status = expr->init(path, strLengthWithStatus.getValue());
- if (!status.isOK()) {
- return status;
- }
- return makeRestriction(BSONType::String, std::move(expr), typeExpr);
-}
-
-StatusWithMatchExpression parsePattern(StringData path,
- BSONElement pattern,
- TypeMatchExpression* typeExpr) {
- if (pattern.type() != BSONType::String) {
- return {Status(ErrorCodes::TypeMismatch,
- str::stream() << "$jsonSchema keyword '" << kSchemaPatternKeyword
- << "' must be a string")};
- }
-
- if (path.empty()) {
- return {stdx::make_unique<AlwaysTrueMatchExpression>()};
- }
-
- auto expr = stdx::make_unique<RegexMatchExpression>();
-
- // JSON Schema does not allow regex flags to be specified.
- constexpr auto emptyFlags = "";
- auto status = expr->init(path, pattern.valueStringData(), emptyFlags);
- if (!status.isOK()) {
- return status;
- }
- return makeRestriction(BSONType::String, std::move(expr), typeExpr);
-}
-
} // namespace
StatusWithMatchExpression JSONSchemaParser::_parseProperties(StringData path,
@@ -315,10 +257,7 @@ StatusWithMatchExpression JSONSchemaParser::_parse(StringData path, BSONObj sche
{kSchemaMaximumKeyword, {}},
{kSchemaMinimumKeyword, {}},
{kSchemaExclusiveMaximumKeyword, {}},
- {kSchemaExclusiveMinimumKeyword, {}},
- {kSchemaMaxLengthKeyword, {}},
- {kSchemaMinLengthKeyword, {}},
- {kSchemaPatternKeyword, {}}};
+ {kSchemaExclusiveMinimumKeyword, {}}};
for (auto&& elt : schema) {
auto it = keywordMap.find(elt.fieldNameStringData());
@@ -406,32 +345,6 @@ StatusWithMatchExpression JSONSchemaParser::_parse(StringData path, BSONObj sche
<< " is present")};
}
- if (auto maxLengthElt = keywordMap[kSchemaMaxLengthKeyword]) {
- auto maxLengthExpr = parseStrLength<InternalSchemaMaxLengthMatchExpression>(
- path, maxLengthElt, typeExpr.getValue().get(), kSchemaMaxLengthKeyword);
- if (!maxLengthExpr.isOK()) {
- return maxLengthExpr;
- }
- andExpr->add(maxLengthExpr.getValue().release());
- }
-
- if (auto minLengthElt = keywordMap[kSchemaMinLengthKeyword]) {
- auto minLengthExpr = parseStrLength<InternalSchemaMinLengthMatchExpression>(
- path, minLengthElt, typeExpr.getValue().get(), kSchemaMinLengthKeyword);
- if (!minLengthExpr.isOK()) {
- return minLengthExpr;
- }
- andExpr->add(minLengthExpr.getValue().release());
- }
-
- if (auto patternElt = keywordMap[kSchemaPatternKeyword]) {
- auto patternExpr = parsePattern(path, patternElt, typeExpr.getValue().get());
- if (!patternExpr.isOK()) {
- return patternExpr;
- }
- andExpr->add(patternExpr.getValue().release());
- }
-
if (path.empty() && typeExpr.getValue() &&
typeExpr.getValue()->getBSONType() != BSONType::Object) {
// This is a top-level schema which requires that the type is something other than
diff --git a/src/mongo/db/matcher/schema/json_schema_parser_test.cpp b/src/mongo/db/matcher/schema/json_schema_parser_test.cpp
index 81f43b7f6a2..a0de359d855 100644
--- a/src/mongo/db/matcher/schema/json_schema_parser_test.cpp
+++ b/src/mongo/db/matcher/schema/json_schema_parser_test.cpp
@@ -36,19 +36,19 @@ namespace mongo {
namespace {
TEST(JSONSchemaParserTest, FailsToParseIfTypeIsNotAString) {
- BSONObj schema = fromjson("{type: 1}");
+ BSONObj schema = fromjson("{type: 1}}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
}
TEST(JSONSchemaParserTest, FailsToParseUnknownKeyword) {
- BSONObj schema = fromjson("{unknown: 1}");
+ BSONObj schema = fromjson("{unknown: 1}}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
}
TEST(JSONSchemaParserTest, FailsToParseIfPropertiesIsNotAnObject) {
- BSONObj schema = fromjson("{properties: 1}");
+ BSONObj schema = fromjson("{properties: 1}}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
}
@@ -178,70 +178,63 @@ TEST(JSONSchemaParserTest, MaximumTranslatesCorrectlyWithNoType) {
"{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$lte: 0}}]}]}]}]}"));
}
-TEST(JSONSchemaParserTest, FailsToParseIfMaximumIsNotANumber) {
- BSONObj schema = fromjson("{maximum: 'foo'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfMaxLengthIsNotANumber) {
- BSONObj schema = fromjson("{maxLength: 'foo'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfMaxLengthIsLessThanZero) {
- BSONObj schema = fromjson("{maxLength: -1}");
+TEST(JSONSchemaParserTest, MaximumTranslatesCorrectlyWithExclusiveMaximumTrue) {
+ BSONObj schema = fromjson(
+ "{properties: {num: {type: 'long', maximum: 0, exclusiveMaximum: true}}, type: 'object'}");
auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
+ ASSERT_OK(result.getStatus());
+ BSONObjBuilder builder;
+ result.getValue()->serialize(&builder);
+ ASSERT_BSONOBJ_EQ(builder.obj(),
+ fromjson("{$and: [{$and: [{$and: ["
+ "{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$lt: 0}}]},"
+ "{$or: [{$nor: [{num: {$exists: true}}]}, {num: {$type: 18}}]}"
+ "]}]}]}"));
}
-TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithTypeNumber) {
- BSONObj schema = fromjson("{properties: {num: {type: 'number', minimum: 0}}, type: 'object'}");
+TEST(JSONSchemaParserTest, MaximumTranslatesCorrectlyWithExclusiveMaximumFalse) {
+ BSONObj schema = fromjson(
+ "{properties: {num: {type: 'long', maximum: 0, exclusiveMaximum: false}}, type: 'object'}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_OK(result.getStatus());
BSONObjBuilder builder;
result.getValue()->serialize(&builder);
ASSERT_BSONOBJ_EQ(builder.obj(),
fromjson("{$and: [{$and: [{$and: ["
- "{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$gte: 0}}]},"
- "{$or: [{$nor: [{num: {$exists: true}}]}, {num: {$type: 'number'}}]}"
+ "{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$lte: 0}}]},"
+ "{$or: [{$nor: [{num: {$exists: true}}]}, {num: {$type: 18}}]}"
"]}]}]}"));
}
-TEST(JSONSchemaParserTest, FailsToParseIfMaxLengthIsNonIntegralDouble) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', maxLength: 5.5}}, type: 'object'}");
+TEST(JSONSchemaParserTest, FailsToParseIfMaximumIsNotANumber) {
+ BSONObj schema = fromjson("{maximum: 'foo'}");
+ auto result = JSONSchemaParser::parse(schema);
+ ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
+}
+
+TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMaximumIsPresentButMaximumIsNot) {
+ BSONObj schema = fromjson("{exclusiveMaximum: true}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
}
-TEST(JSONSchemaParserTest, MaxLengthTranslatesCorrectlyWithIntegralDouble) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', maxLength: 5.0}}, type: 'object'}");
+TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMaximumIsNotABoolean) {
+ BSONObj schema = fromjson("{maximum: 5, exclusiveMaximum: 'foo'}");
auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(
- builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { foo: { $type: 2 } } ] }, { "
- "foo: { $_internalSchemaMaxLength: 5 } } ] }, { $or: [ { $nor: [ { foo: { "
- "$exists: true } } ] }, { foo: { $type: 2 } } ] } ] } ] } ] }"));
+ ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
}
-TEST(JSONSchemaParserTest, MaxLengthTranslatesCorrectlyWithTypeString) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', maxLength: 5}}, type: 'object'}");
+TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithTypeNumber) {
+ BSONObj schema = fromjson("{properties: {num: {type: 'number', minimum: 0}}, type: 'object'}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_OK(result.getStatus());
BSONObjBuilder builder;
result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(
- builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { foo: { $type: 2 } } ] }, { "
- "foo: { $_internalSchemaMaxLength: 5 } } ] }, { $or: [ { $nor: [ { foo: { "
- "$exists: true } } ] }, { foo: { $type: 2 } } ] } ] } ] } ] }"));
+ ASSERT_BSONOBJ_EQ(builder.obj(),
+ fromjson("{$and: [{$and: [{$and: ["
+ "{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$gte: 0}}]},"
+ "{$or: [{$nor: [{num: {$exists: true}}]}, {num: {$type: 'number'}}]}"
+ "]}]}]}"));
}
TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithTypeLong) {
@@ -281,46 +274,6 @@ TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithNoType) {
"{$or: [{$nor: [{num: {$type: 'number'}}]}, {num: {$gte: 0}}]}]}]}]}"));
}
-TEST(JSONSchemaParserTest, MaximumTranslatesCorrectlyWithExclusiveMaximumTrue) {
- BSONObj schema = fromjson(
- "{properties: {num: {type: 'long', maximum: 0, exclusiveMaximum: true}}, type: 'object'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { "
- "num: { $type: 'number' } } ] }, { num: { $lt: 0 } } "
- "] }, { $or: [ { $nor: [ { num: { $exists: true } } "
- "] }, { num: { $type: 18 } } ] } ] } ] } ] }"));
-}
-
-TEST(JSONSchemaParserTest, MaximumTranslatesCorrectlyWithExclusiveMaximumFalse) {
- BSONObj schema = fromjson(
- "{properties: {num: {type: 'long', maximum: 0, exclusiveMaximum: false}}, type: 'object'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { "
- "num: { $type: 'number' } } ] }, { num: { $lte: 0 } "
- "} ] }, { $or: [ { $nor: [ { num: { $exists: true } "
- "} ] }, { num: { $type: 18 } } ] } ] } ] } ] }"));
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMaximumIsPresentButMaximumIsNot) {
- BSONObj schema = fromjson("{exclusiveMaximum: true}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMaximumIsNotABoolean) {
- BSONObj schema = fromjson("{maximum: 5, exclusiveMaximum: 'foo'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
-}
-
TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithExclusiveMinimumTrue) {
BSONObj schema = fromjson(
"{properties: {num: {type: 'long', minimum: 0, exclusiveMinimum: true}}, type: 'object'}");
@@ -349,99 +302,24 @@ TEST(JSONSchemaParserTest, MinimumTranslatesCorrectlyWithExclusiveMinimumFalse)
"]}]}]}"));
}
-TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMinimumIsPresentButMinimumIsNot) {
- BSONObj schema = fromjson("{exclusiveMinimum: true}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMinimumIsNotABoolean) {
- BSONObj schema = fromjson("{minimum: 5, exclusiveMinimum: 'foo'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfMinLengthIsNotANumber) {
- BSONObj schema = fromjson("{minLength: 'foo'}");
+TEST(JSONSchemaParserTest, FailsToParseIfMinimumIsNotANumber) {
+ BSONObj schema = fromjson("{minimum: 'foo'}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
}
-TEST(JSONSchemaParserTest, FailsToParseIfMinLengthIsLessThanZero) {
- BSONObj schema = fromjson("{minLength: -1}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
-}
-TEST(JSONSchemaParserTest, FailsToParseIfMinLengthIsNonIntegralDouble) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', minLength: 5.5}}, type: 'object'}");
+TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMinimumIsPresentButMinimumIsNot) {
+ BSONObj schema = fromjson("{exclusiveMinimum: true}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
}
-TEST(JSONSchemaParserTest, MinLengthTranslatesCorrectlyWithTypeString) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', minLength: 5}}, type: 'object'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(
- builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { foo: { $type: 2 } } ] }, { "
- "foo: { $_internalSchemaMinLength: 5 } } ] }, { $or: [ { $nor: [ { foo: { "
- "$exists: true } } ] }, { foo: { $type: 2 } } ] } ] } ] } ] }"));
-}
-
-TEST(JSONSchemaParserTest, MinLengthTranslatesCorrectlyWithIntegralDouble) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', minLength: 5.0}}, type: 'object'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
- ASSERT_BSONOBJ_EQ(
- builder.obj(),
- fromjson("{ $and: [ { $and: [ { $and: [ { $or: [ { $nor: [ { foo: { $type: 2 } } ] }, { "
- "foo: { $_internalSchemaMinLength: 5 } } ] }, { $or: [ { $nor: [ { foo: { "
- "$exists: true } } ] }, { foo: { $type: 2 } } ] } ] } ] } ] }"));
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfMinimumIsNotANumber) {
- BSONObj schema = fromjson("{minimum: 'foo'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
-}
-
-TEST(JSONSchemaParserTest, FailsToParseIfPatternIsNotString) {
- BSONObj schema = fromjson("{pattern: 6}");
+TEST(JSONSchemaParserTest, FailsToParseIfExclusiveMinimumIsNotABoolean) {
+ BSONObj schema = fromjson("{minimum: 5, exclusiveMinimum: 'foo'}");
auto result = JSONSchemaParser::parse(schema);
ASSERT_EQ(result.getStatus(), ErrorCodes::TypeMismatch);
}
-TEST(JSONSchemaParserTest, PatternTranslatesCorrectlyWithString) {
- BSONObj schema =
- fromjson("{properties: {foo: {type: 'string', pattern: 'abc'}}, type: 'object'}");
- auto result = JSONSchemaParser::parse(schema);
- ASSERT_OK(result.getStatus());
- BSONObjBuilder builder;
- result.getValue()->serialize(&builder);
-
- BSONObj expected = BSON(
- "$and" << BSON_ARRAY(BSON(
- "$and" << BSON_ARRAY(BSON(
- "$and" << BSON_ARRAY(
- BSON("$or" << BSON_ARRAY(
- BSON("$nor" << BSON_ARRAY(BSON("foo" << BSON("$type" << 2))))
- << BSON("foo" << BSON("$regex"
- << "abc"))))
- << BSON("$or" << BSON_ARRAY(
- BSON("$nor" << BSON_ARRAY(BSON("foo" << BSON("$exists" << true))))
- << BSON("foo" << BSON("$type" << 2))))))))));
-
- ASSERT_BSONOBJ_EQ(builder.obj(), expected);
-}
-
} // namespace
} // namespace mongo