diff options
author | Gregory Wlodarek <gregory.wlodarek@mongodb.com> | 2019-09-24 10:42:47 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-09-24 10:42:47 +0000 |
commit | ed9d2602949314e87562219b354a2d9f0737fd52 (patch) | |
tree | e82240567222c5c8ee60c02156f9265b26e392b4 | |
parent | 7dd8f43da5241570853d27eb8f55888f4e059f66 (diff) | |
download | mongo-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.cpp | 50 |
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 |