summaryrefslogtreecommitdiff
path: root/src/mongo/db/s/shard_key_index_util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/s/shard_key_index_util.cpp')
-rw-r--r--src/mongo/db/s/shard_key_index_util.cpp73
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