summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/catalog')
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp2
-rw-r--r--src/mongo/db/catalog/index_key_validate.cpp86
-rw-r--r--src/mongo/db/catalog/index_key_validate.h39
3 files changed, 85 insertions, 42 deletions
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 4e15e370a20..bcfe8cc156f 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1858,7 +1858,7 @@ std::vector<std::string> CollectionImpl::removeInvalidIndexOptions(OperationCont
}
indexesWithInvalidOptions.push_back(std::string(index.name()));
- index.spec = index_key_validate::removeUnknownFields(oldSpec);
+ index.spec = index_key_validate::removeUnknownFields(NamespaceString(md.ns), oldSpec);
}
});
diff --git a/src/mongo/db/catalog/index_key_validate.cpp b/src/mongo/db/catalog/index_key_validate.cpp
index 87ebafdd23a..a22263b7674 100644
--- a/src/mongo/db/catalog/index_key_validate.cpp
+++ b/src/mongo/db/catalog/index_key_validate.cpp
@@ -68,35 +68,6 @@ namespace {
// specification.
MONGO_FAIL_POINT_DEFINE(skipIndexCreateFieldNameValidation);
-static std::set<StringData> allowedFieldNames = {
- IndexDescriptor::k2dIndexBitsFieldName,
- IndexDescriptor::k2dIndexMaxFieldName,
- IndexDescriptor::k2dIndexMinFieldName,
- IndexDescriptor::k2dsphereCoarsestIndexedLevel,
- IndexDescriptor::k2dsphereFinestIndexedLevel,
- IndexDescriptor::k2dsphereVersionFieldName,
- IndexDescriptor::kBackgroundFieldName,
- IndexDescriptor::kCollationFieldName,
- IndexDescriptor::kDefaultLanguageFieldName,
- IndexDescriptor::kDropDuplicatesFieldName,
- IndexDescriptor::kExpireAfterSecondsFieldName,
- IndexDescriptor::kGeoHaystackBucketSize,
- IndexDescriptor::kHiddenFieldName,
- IndexDescriptor::kIndexNameFieldName,
- IndexDescriptor::kIndexVersionFieldName,
- IndexDescriptor::kKeyPatternFieldName,
- IndexDescriptor::kLanguageOverrideFieldName,
- IndexDescriptor::kNamespaceFieldName,
- IndexDescriptor::kPartialFilterExprFieldName,
- IndexDescriptor::kPathProjectionFieldName,
- IndexDescriptor::kSparseFieldName,
- IndexDescriptor::kStorageEngineFieldName,
- IndexDescriptor::kTextVersionFieldName,
- IndexDescriptor::kUniqueFieldName,
- IndexDescriptor::kWeightsFieldName,
- // Index creation under legacy writeMode can result in an index spec with an _id field.
- "_id"};
-
static const std::set<StringData> allowedIdIndexFieldNames = {
IndexDescriptor::kCollationFieldName,
IndexDescriptor::kIndexNameFieldName,
@@ -120,6 +91,27 @@ Status isIndexVersionAllowedForCreation(IndexVersion indexVersion, const BSONObj
str::stream() << "Invalid index specification " << indexSpec
<< "; cannot create an index with v=" << static_cast<int>(indexVersion)};
}
+
+BSONObj buildRepairedIndexSpec(
+ const NamespaceString& ns,
+ const BSONObj& indexSpec,
+ const std::set<StringData>& allowedFieldNames,
+ std::function<void(const BSONElement&, BSONObjBuilder*)> indexSpecHandleFn) {
+ BSONObjBuilder builder;
+ for (const auto& indexSpecElem : indexSpec) {
+ StringData fieldName = indexSpecElem.fieldNameStringData();
+ if (allowedFieldNames.count(fieldName)) {
+ indexSpecHandleFn(indexSpecElem, &builder);
+ } else {
+ LOGV2_WARNING(23878,
+ "Removing unknown field from index spec",
+ "namespace"_attr = redact(ns.toString()),
+ "fieldName"_attr = redact(fieldName),
+ "indexSpec"_attr = redact(indexSpec));
+ }
+ }
+ return builder.obj();
+}
} // namespace
Status validateKeyPattern(const BSONObj& key, IndexDescriptor::IndexVersion indexVersion) {
@@ -250,21 +242,35 @@ Status validateKeyPattern(const BSONObj& key, IndexDescriptor::IndexVersion inde
return Status::OK();
}
-BSONObj removeUnknownFields(const BSONObj& indexSpec) {
- BSONObjBuilder builder;
- for (const auto& indexSpecElem : indexSpec) {
+BSONObj removeUnknownFields(const NamespaceString& ns, const BSONObj& indexSpec) {
+ auto appendIndexSpecFn = [](const BSONElement& indexSpecElem, BSONObjBuilder* builder) {
+ builder->append(indexSpecElem);
+ };
+ return buildRepairedIndexSpec(ns, indexSpec, allowedFieldNames, appendIndexSpecFn);
+}
+
+BSONObj repairIndexSpec(const NamespaceString& ns,
+ const BSONObj& indexSpec,
+ const std::set<StringData>& allowedFieldNames) {
+ auto fixBoolIndexSpecFn = [&indexSpec, &ns](const BSONElement& indexSpecElem,
+ BSONObjBuilder* builder) {
StringData fieldName = indexSpecElem.fieldNameStringData();
- if (allowedFieldNames.count(fieldName)) {
- builder.append(indexSpecElem);
- } else {
- LOGV2_WARNING(23878,
- "Removing field '{fieldName}' from index spec: {indexSpec}",
- "Removing unknown field from index spec",
+ if ((IndexDescriptor::kBackgroundFieldName == fieldName ||
+ IndexDescriptor::kUniqueFieldName == fieldName ||
+ IndexDescriptor::kSparseFieldName == fieldName ||
+ IndexDescriptor::kDropDuplicatesFieldName == fieldName) &&
+ !indexSpecElem.isNumber() && !indexSpecElem.isBoolean() && indexSpecElem.trueValue()) {
+ LOGV2_WARNING(6444400,
+ "Fixing boolean field from index spec",
+ "namespace"_attr = redact(ns.toString()),
"fieldName"_attr = redact(fieldName),
"indexSpec"_attr = redact(indexSpec));
+ builder->appendBool(fieldName, true);
+ } else {
+ builder->append(indexSpecElem);
}
- }
- return builder.obj();
+ };
+ return buildRepairedIndexSpec(ns, indexSpec, allowedFieldNames, fixBoolIndexSpecFn);
}
StatusWith<BSONObj> validateIndexSpec(OperationContext* opCtx, const BSONObj& indexSpec) {
diff --git a/src/mongo/db/catalog/index_key_validate.h b/src/mongo/db/catalog/index_key_validate.h
index b170550b0e7..332572d41d0 100644
--- a/src/mongo/db/catalog/index_key_validate.h
+++ b/src/mongo/db/catalog/index_key_validate.h
@@ -43,6 +43,35 @@ class StatusWith;
namespace index_key_validate {
+static std::set<StringData> allowedFieldNames = {
+ IndexDescriptor::k2dIndexBitsFieldName,
+ IndexDescriptor::k2dIndexMaxFieldName,
+ IndexDescriptor::k2dIndexMinFieldName,
+ IndexDescriptor::k2dsphereCoarsestIndexedLevel,
+ IndexDescriptor::k2dsphereFinestIndexedLevel,
+ IndexDescriptor::k2dsphereVersionFieldName,
+ IndexDescriptor::kBackgroundFieldName,
+ IndexDescriptor::kCollationFieldName,
+ IndexDescriptor::kDefaultLanguageFieldName,
+ IndexDescriptor::kDropDuplicatesFieldName,
+ IndexDescriptor::kExpireAfterSecondsFieldName,
+ IndexDescriptor::kGeoHaystackBucketSize,
+ IndexDescriptor::kHiddenFieldName,
+ IndexDescriptor::kIndexNameFieldName,
+ IndexDescriptor::kIndexVersionFieldName,
+ IndexDescriptor::kKeyPatternFieldName,
+ IndexDescriptor::kLanguageOverrideFieldName,
+ IndexDescriptor::kNamespaceFieldName,
+ IndexDescriptor::kPartialFilterExprFieldName,
+ IndexDescriptor::kPathProjectionFieldName,
+ IndexDescriptor::kSparseFieldName,
+ IndexDescriptor::kStorageEngineFieldName,
+ IndexDescriptor::kTextVersionFieldName,
+ IndexDescriptor::kUniqueFieldName,
+ IndexDescriptor::kWeightsFieldName,
+ // Index creation under legacy writeMode can result in an index spec with an _id field.
+ "_id"};
+
/**
* Checks if the key is valid for building an index according to the validation rules for the given
* index version.
@@ -59,7 +88,15 @@ StatusWith<BSONObj> validateIndexSpec(OperationContext* opCtx, const BSONObj& in
/**
* Returns a new index spec with any unknown field names removed from 'indexSpec'.
*/
-BSONObj removeUnknownFields(const BSONObj& indexSpec);
+BSONObj removeUnknownFields(const NamespaceString& ns, const BSONObj& indexSpec);
+
+/**
+ * Returns a new index spec with boolean values in correct types and unkown field names removed.
+ */
+BSONObj repairIndexSpec(
+ const NamespaceString& ns,
+ const BSONObj& indexSpec,
+ const std::set<StringData>& allowedFieldNames = index_key_validate::allowedFieldNames);
/**
* Performs additional validation for _id index specifications. This should be called after