diff options
Diffstat (limited to 'src/mongo/db/s/shard_key_index_util.cpp')
-rw-r--r-- | src/mongo/db/s/shard_key_index_util.cpp | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/src/mongo/db/s/shard_key_index_util.cpp b/src/mongo/db/s/shard_key_index_util.cpp index 9b3b6371a4a..1cdd4f99008 100644 --- a/src/mongo/db/s/shard_key_index_util.cpp +++ b/src/mongo/db/s/shard_key_index_util.cpp @@ -48,7 +48,8 @@ boost::optional<ShardKeyIndex> _findShardKeyPrefixedIndex( const IndexCatalog* indexCatalog, const boost::optional<std::string>& excludeName, const BSONObj& shardKey, - bool requireSingleKey) { + bool requireSingleKey, + std::string* errMsg = nullptr) { if (collection->isClustered() && clustered_util::matchesClusterKey(shardKey, collection->getClusteredInfo())) { auto clusteredIndexSpec = collection->getClusteredInfo()->getIndexSpec(); @@ -67,7 +68,8 @@ boost::optional<ShardKeyIndex> _findShardKeyPrefixedIndex( continue; } - if (isCompatibleWithShardKey(opCtx, collection, indexEntry, shardKey, requireSingleKey)) { + if (isCompatibleWithShardKey( + opCtx, collection, indexEntry, shardKey, requireSingleKey, errMsg)) { if (!indexEntry->isMultikey(opCtx, collection)) { return ShardKeyIndex(indexDescriptor); } @@ -108,26 +110,72 @@ bool isCompatibleWithShardKey(OperationContext* opCtx, const CollectionPtr& collection, const IndexCatalogEntry* indexEntry, const BSONObj& shardKey, - bool requireSingleKey) { + bool requireSingleKey, + std::string* errMsg) { + // Return a descriptive error for each index that shares a prefix with shardKey but + // cannot be used for sharding. + const int kErrorPartial = 0x01; + const int kErrorSparse = 0x02; + const int kErrorMultikey = 0x04; + const int kErrorCollation = 0x08; + const int kErrorNotPrefix = 0x10; + int reasons = 0; + auto desc = indexEntry->descriptor(); bool hasSimpleCollation = desc->collation().isEmpty(); - if (desc->isPartial() || desc->isSparse()) { - return false; + if (desc->isPartial()) { + reasons |= kErrorPartial; + } + + if (desc->isSparse()) { + reasons |= kErrorSparse; } if (!shardKey.isPrefixOf(desc->keyPattern(), SimpleBSONElementComparator::kInstance)) { - return false; + reasons |= kErrorNotPrefix; } - if (!indexEntry->isMultikey(opCtx, collection) && hasSimpleCollation) { - return true; + if (reasons == 0) { // that is, not partial index, not sparse, and not prefix, then: + if (!indexEntry->isMultikey(opCtx, collection)) { + if (hasSimpleCollation) { + return true; + } + } else { + reasons |= kErrorMultikey; + } + if (!requireSingleKey && hasSimpleCollation) { + return true; + } } - if (!requireSingleKey && hasSimpleCollation) { - return true; + if (!hasSimpleCollation) { + reasons |= kErrorCollation; } + if (errMsg && reasons != 0) { + std::string errors = "Index " + indexEntry->descriptor()->indexName() + + " cannot be used for sharding because:"; + if (reasons & kErrorPartial) { + errors += " Index key is partial."; + } + if (reasons & kErrorSparse) { + errors += " Index key is sparse."; + } + if (reasons & kErrorMultikey) { + errors += " Index key is multikey."; + } + if (reasons & kErrorCollation) { + errors += " Index has a non-simple collation."; + } + if (reasons & kErrorNotPrefix) { + errors += " Shard key is not a prefix of index key."; + } + if (!errMsg->empty()) { + *errMsg += "\n"; + } + *errMsg += errors; + } return false; } @@ -145,9 +193,10 @@ boost::optional<ShardKeyIndex> findShardKeyPrefixedIndex(OperationContext* opCtx const CollectionPtr& collection, const IndexCatalog* indexCatalog, const BSONObj& shardKey, - bool requireSingleKey) { + bool requireSingleKey, + std::string* errMsg) { return _findShardKeyPrefixedIndex( - opCtx, collection, indexCatalog, boost::none, shardKey, requireSingleKey); + opCtx, collection, indexCatalog, boost::none, shardKey, requireSingleKey, errMsg); } } // namespace mongo |