summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2016-12-12 11:46:58 -0500
committerCharlie Swanson <charlie.swanson@mongodb.com>2016-12-13 13:15:02 -0500
commit68908f8e03ee1a4c0400dae26cc20b0c304b913b (patch)
treecf5638832ea0fffbf4c0b6173dd1526cae3c97a1
parent0240b9c2e39ae05c607b34b66573bb972ef1f66f (diff)
downloadmongo-68908f8e03ee1a4c0400dae26cc20b0c304b913b.tar.gz
SERVER-27243 Ignore invalid collection options if 'create' present
It is possible for older versions of MongoDB to save invalid collection options which should be ignored. Older versions also would include a 'create' field in the collection options when a collection was created, and possibly re-order the fields of the options document during a subsequent 'collMod'. If the 'create' option is present at all, we should take that to mean that these options were created on an older version of MongoDB, and ignore unknown options. Otherwise, we should reject unknown options. (cherry picked from commit 6fba074768fad5f47611de38682257257005a1a6)
-rw-r--r--src/mongo/db/catalog/collection_options.cpp17
-rw-r--r--src/mongo/db/catalog/collection_options_test.cpp28
2 files changed, 30 insertions, 15 deletions
diff --git a/src/mongo/db/catalog/collection_options.cpp b/src/mongo/db/catalog/collection_options.cpp
index d2f3f452a0a..0a576d3c5d2 100644
--- a/src/mongo/db/catalog/collection_options.cpp
+++ b/src/mongo/db/catalog/collection_options.cpp
@@ -132,26 +132,21 @@ Status CollectionOptions::validate() const {
Status CollectionOptions::parse(const BSONObj& options) {
reset();
- // Versions 2.4 and earlier of the server store "create" as the first field inside the
- // collection metadata when the user issues an explicit collection creation command. These
- // versions also wrote any unrecognized fields into the catalog metadata. Therefore, if the
- // "create" field is present and first, we must ignore any unknown fields during parsing.
- // Otherwise, we disallow unknown collection options.
+ // Versions 2.4 and earlier of the server store "create" inside the collection metadata when the
+ // user issues an explicit collection creation command. These versions also wrote any
+ // unrecognized fields into the catalog metadata and allowed the order of these fields to be
+ // changed. Therefore, if the "create" field is present, we must ignore any
+ // unknown fields during parsing. Otherwise, we disallow unknown collection options.
//
// Versions 2.6 through 3.2 ignored unknown collection options rather than failing but did not
// store the "create" field. These versions also refrained from materializing the unknown
// options in the catalog, so we are free to fail on unknown options in this case.
- const bool createdOn24OrEarlier = (options.firstElement().fieldNameStringData() == "create"_sd);
+ const bool createdOn24OrEarlier = static_cast<bool>(options["create"]);
// During parsing, ignore some validation errors in order to accept options objects that
// were valid in previous versions of the server. SERVER-13737.
BSONObjIterator i(options);
- // Skip the initial "create" field, if present.
- if (createdOn24OrEarlier) {
- i.next();
- }
-
while (i.more()) {
BSONElement e = i.next();
StringData fieldName = e.fieldName();
diff --git a/src/mongo/db/catalog/collection_options_test.cpp b/src/mongo/db/catalog/collection_options_test.cpp
index aa500997049..71f6b28fa29 100644
--- a/src/mongo/db/catalog/collection_options_test.cpp
+++ b/src/mongo/db/catalog/collection_options_test.cpp
@@ -276,22 +276,42 @@ TEST(CollectionOptions, CreateOptionIgnoredIfFirst) {
ASSERT_OK(status);
}
+TEST(CollectionOptions, CreateOptionIgnoredIfNotFirst) {
+ CollectionOptions options;
+ auto status = options.parse(fromjson("{capped: true, create: 1, size: 1024}"));
+ ASSERT_OK(status);
+ ASSERT_EQ(options.capped, true);
+ ASSERT_EQ(options.cappedSize, 1024L);
+}
+
TEST(CollectionOptions, UnknownOptionIgnoredIfCreateOptionFirst) {
CollectionOptions options;
ASSERT_OK(options.parse(fromjson("{create: 1, invalidOption: 1}")));
}
+TEST(CollectionOptions, UnknownOptionIgnoredIfCreateOptionPresent) {
+ CollectionOptions options;
+ ASSERT_OK(options.parse(fromjson("{invalidOption: 1, create: 1}")));
+}
+
+TEST(CollectionOptions, UnknownOptionRejectedIfCreateOptionNotPresent) {
+ CollectionOptions options;
+ auto status = options.parse(fromjson("{invalidOption: 1}"));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQ(status.code(), ErrorCodes::InvalidOptions);
+}
+
TEST(CollectionOptions, DuplicateCreateOptionIgnoredIfCreateOptionFirst) {
CollectionOptions options;
auto status = options.parse(BSON("create" << 1 << "create" << 1));
ASSERT_OK(status);
}
-TEST(CollectionOptions, CreateOptionRejectedIfNotFirst) {
+TEST(CollectionOptions, DuplicateCreateOptionIgnoredIfCreateOptionNotFirst) {
CollectionOptions options;
- auto status = options.parse(fromjson("{validator: {a: 1}, create: 1}"));
- ASSERT_NOT_OK(status);
- ASSERT_EQ(status.code(), ErrorCodes::InvalidOptions);
+ auto status =
+ options.parse(BSON("capped" << true << "create" << 1 << "create" << 1 << "size" << 1024));
+ ASSERT_OK(status);
}
TEST(CollectionOptions, MaxTimeMSWhitelistedOptionIgnored) {