summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-09-24 13:04:51 +0000
committerevergreen <evergreen@mongodb.com>2019-09-24 13:04:51 +0000
commitcee48bf8f043912adffbcf8fe10dc248f1810466 (patch)
tree461ac699b39d6128b120374dcbff03ceb4689895
parent1833f38080379a231f2bc4ec8fe4e9a6ae2cb0dc (diff)
downloadmongo-cee48bf8f043912adffbcf8fe10dc248f1810466.tar.gz
SERVER-43081 validate should report when an index's 'multikeyPaths' are set but the 'multikey' flag is false
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 6b70435b785..4c05bfcb501 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1303,6 +1303,35 @@ void addErrorIfUnequal(T stored, T cached, StringData name, ValidateResults* res
}
}
+std::string multikeyPathsToString(MultikeyPaths paths) {
+ str::stream builder;
+ builder << "[";
+ auto pathIt = paths.begin();
+ while (true) {
+ builder << "{";
+
+ auto pathSet = *pathIt;
+ auto setIt = pathSet.begin();
+ while (true) {
+ builder << *setIt++;
+ if (setIt == pathSet.end()) {
+ break;
+ } else {
+ builder << ",";
+ }
+ }
+ builder << "}";
+
+ if (++pathIt == paths.end()) {
+ break;
+ } else {
+ builder << ",";
+ }
+ }
+ builder << "]";
+ return builder;
+}
+
void _validateCatalogEntry(OperationContext* opCtx,
CollectionImpl* coll,
BSONObj validatorDoc,
@@ -1337,6 +1366,34 @@ void _validateCatalogEntry(OperationContext* opCtx,
results->errors.push_back(str::stream() << "collection options are not valid for storage: "
<< options.toBSON());
}
+
+ std::vector<std::string> indexes;
+ IndexCatalog::IndexIterator i = coll->getIndexCatalog()->getIndexIterator(opCtx, false);
+ while (i.more()) {
+ const IndexDescriptor* descriptor = i.next();
+ if (coll->getCatalogEntry()->isIndexReady(opCtx, descriptor->indexName())) {
+ indexes.push_back(descriptor->indexName());
+ }
+ }
+
+ for (auto& index : indexes) {
+ MultikeyPaths multikeyPaths;
+ const bool isMultikey =
+ coll->getCatalogEntry()->isIndexMultikey(opCtx, index, &multikeyPaths);
+ const bool hasMultiKeyPaths = std::any_of(multikeyPaths.begin(),
+ multikeyPaths.end(),
+ [](auto& pathSet) { return pathSet.size() > 0; });
+ // It is illegal for multikey paths to exist without the multikey flag set on the index, but
+ // it may be possible for multikey to be set on the index while having no multikey paths. If
+ // any of the paths are multikey, then the entire index should also be marked multikey.
+ if (hasMultiKeyPaths && !isMultikey) {
+ results->valid = false;
+ string err = str::stream() << "The 'multikey' field for index " << index
+ << " was false with non-empty 'multikeyPaths': "
+ << multikeyPathsToString(multikeyPaths);
+ results->errors.push_back(err);
+ }
+ }
}
} // namespace