summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-09-24 10:42:47 +0000
committerevergreen <evergreen@mongodb.com>2019-09-24 10:42:47 +0000
commited9d2602949314e87562219b354a2d9f0737fd52 (patch)
treee82240567222c5c8ee60c02156f9265b26e392b4
parent7dd8f43da5241570853d27eb8f55888f4e059f66 (diff)
downloadmongo-ed9d2602949314e87562219b354a2d9f0737fd52.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.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 8367b3d96f1..613bfb21bbe 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1311,6 +1311,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,
@@ -1345,6 +1374,27 @@ void _validateCatalogEntry(OperationContext* opCtx,
results->errors.push_back(str::stream() << "collection options are not valid for storage: "
<< options.toBSON());
}
+
+ std::vector<std::string> indexes;
+ coll->getCatalogEntry()->getReadyIndexes(opCtx, &indexes);
+ 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