summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Golfieri <enrico.golfieri@mongodb.com>2022-09-08 15:03:23 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-08 15:24:36 +0000
commit95f7351385d89754877e239bfbe59acf644ba883 (patch)
treeddf96f2633c57e8b6be433f37599552af0d22e79
parent39067ac3ef739a47970637e0cbd20250dd0e694d (diff)
downloadmongo-95f7351385d89754877e239bfbe59acf644ba883.tar.gz
SERVER-69220 refineCollectionShardKey permits toggling current shard key fields between range-based and hashed, leading to data inconsistency
-rw-r--r--src/mongo/s/shard_key_pattern.cpp3
-rw-r--r--src/mongo/s/shard_key_pattern_test.cpp78
2 files changed, 80 insertions, 1 deletions
diff --git a/src/mongo/s/shard_key_pattern.cpp b/src/mongo/s/shard_key_pattern.cpp
index 46f3290ec33..675dcd5964d 100644
--- a/src/mongo/s/shard_key_pattern.cpp
+++ b/src/mongo/s/shard_key_pattern.cpp
@@ -33,6 +33,7 @@
#include <vector>
+#include "mongo/bson/simple_bsonelement_comparator.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/field_ref_set.h"
#include "mongo/db/hasher.h"
@@ -277,7 +278,7 @@ bool ShardKeyPattern::isShardKey(const BSONObj& shardKey) const {
}
bool ShardKeyPattern::isExtendedBy(const ShardKeyPattern& newShardKeyPattern) const {
- return toBSON().isFieldNamePrefixOf(newShardKeyPattern.toBSON());
+ return toBSON().isPrefixOf(newShardKeyPattern.toBSON(), SimpleBSONElementComparator::kInstance);
}
BSONObj ShardKeyPattern::normalizeShardKey(const BSONObj& shardKey) const {
diff --git a/src/mongo/s/shard_key_pattern_test.cpp b/src/mongo/s/shard_key_pattern_test.cpp
index 7910ebc6bd3..f01d29359cd 100644
--- a/src/mongo/s/shard_key_pattern_test.cpp
+++ b/src/mongo/s/shard_key_pattern_test.cpp
@@ -884,5 +884,83 @@ TEST(ShardKeyPattern, ExtractShardKeyFromIndexKeyData_FromMultipleIndexesProvidi
<< "a.thirdIndex" << hashedValue << "null" << BSONNULL));
}
+TEST(ShardKeyPattern, IsExtendedBy) {
+
+ // NumberOfFields
+ ShardKeyPattern shardKeyPattern1(BSON("a" << 1));
+ ShardKeyPattern shardKeyPattern2(BSON("a" << 1 << "b" << 1));
+ ShardKeyPattern shardKeyPattern3(BSON("a" << 1 << "b" << 1 << "c" << 1));
+
+ // NumberOfFields_PositionOfHash
+ ShardKeyPattern shardKeyPatternHashed1_0(BSON("a"
+ << "hashed"));
+ ShardKeyPattern shardKeyPatternHashed2_0(BSON("a"
+ << "hashed"
+ << "b" << 1));
+ ShardKeyPattern shardKeyPatternHashed2_1(BSON("a" << 1 << "b"
+ << "hashed"));
+ ShardKeyPattern shardKeyPatternHashed3_0(BSON("a"
+ << "hashed"
+ << "b" << 1 << "c" << 1));
+ ShardKeyPattern shardKeyPatternHashed3_1(BSON("a" << 1 << "b"
+ << "hashed"
+ << "c" << 1));
+ ShardKeyPattern shardKeyPatternHashed3_2(BSON("a" << 1 << "b" << 1 << "c"
+ << "hashed"));
+
+ // same pattern, always true
+ ASSERT_TRUE(shardKeyPattern1.isExtendedBy(shardKeyPattern1));
+ ASSERT_TRUE(shardKeyPattern2.isExtendedBy(shardKeyPattern2));
+ ASSERT_TRUE(shardKeyPattern3.isExtendedBy(shardKeyPattern3));
+ ASSERT_TRUE(shardKeyPatternHashed1_0.isExtendedBy(shardKeyPatternHashed1_0));
+ ASSERT_TRUE(shardKeyPatternHashed2_0.isExtendedBy(shardKeyPatternHashed2_0));
+ ASSERT_TRUE(shardKeyPatternHashed2_1.isExtendedBy(shardKeyPatternHashed2_1));
+ ASSERT_TRUE(shardKeyPatternHashed3_0.isExtendedBy(shardKeyPatternHashed3_0));
+ ASSERT_TRUE(shardKeyPatternHashed3_1.isExtendedBy(shardKeyPatternHashed3_1));
+ ASSERT_TRUE(shardKeyPatternHashed3_2.isExtendedBy(shardKeyPatternHashed3_2));
+
+ // different number of fields, same values
+ ASSERT_TRUE(shardKeyPattern1.isExtendedBy(shardKeyPattern2));
+ ASSERT_TRUE(shardKeyPattern2.isExtendedBy(shardKeyPattern3));
+ ASSERT_TRUE(shardKeyPattern1.isExtendedBy(shardKeyPattern3));
+
+ ASSERT_FALSE(shardKeyPattern2.isExtendedBy(shardKeyPattern1));
+ ASSERT_FALSE(shardKeyPattern3.isExtendedBy(shardKeyPattern2));
+ ASSERT_FALSE(shardKeyPattern3.isExtendedBy(shardKeyPattern1));
+
+ // different number of fields, different values
+ // { a : 1 } is not extended by { a : "hashed" } and viceversa
+ ASSERT_FALSE(shardKeyPattern1.isExtendedBy(shardKeyPatternHashed1_0));
+ ASSERT_FALSE(shardKeyPatternHashed1_0.isExtendedBy(shardKeyPattern1));
+
+ // { a : 1, b : 1 } is not extended by { a : 1, b : "hashed" } and viceversa
+ ASSERT_FALSE(shardKeyPattern2.isExtendedBy(shardKeyPatternHashed2_1));
+ ASSERT_FALSE(shardKeyPatternHashed2_1.isExtendedBy(shardKeyPattern2));
+
+ // { a : 1 } is extended by { a : 1, b : "hashed" } but not viceversa
+ ASSERT_TRUE(shardKeyPattern1.isExtendedBy(shardKeyPatternHashed2_1));
+ ASSERT_FALSE(shardKeyPatternHashed2_1.isExtendedBy(shardKeyPattern1));
+
+ // { a : 1, b : 1 } is extended by { a : 1, b : 1, c : "hashed" } but not viceversa
+ ASSERT_TRUE(shardKeyPattern2.isExtendedBy(shardKeyPatternHashed3_2));
+ ASSERT_FALSE(shardKeyPatternHashed3_2.isExtendedBy(shardKeyPattern2));
+
+ // { a : 1, b : 1, c : 1 } is not extended by { a : 1, b : 1, c : "hashed" } and viceversa
+ ASSERT_FALSE(shardKeyPattern3.isExtendedBy(shardKeyPatternHashed3_2));
+ ASSERT_FALSE(shardKeyPatternHashed3_2.isExtendedBy(shardKeyPattern3));
+
+ // { a: "hashed", b : 1 } is not extended by { a : 1, b : 1, c : "hashed" } and viceversa
+ ASSERT_FALSE(shardKeyPatternHashed2_1.isExtendedBy(shardKeyPatternHashed3_2));
+ ASSERT_FALSE(shardKeyPatternHashed3_2.isExtendedBy(shardKeyPatternHashed2_1));
+
+ // { a : "hashed", b : 1 } is extended by { a : "hashed", b : 1, c : "1" } but not viceversa
+ ASSERT_TRUE(shardKeyPatternHashed2_0.isExtendedBy(shardKeyPatternHashed3_0));
+ ASSERT_FALSE(shardKeyPatternHashed3_0.isExtendedBy(shardKeyPatternHashed2_0));
+
+ // { a : 1, b : "hashed " } is extended by { a : 1, b : "hashed", c : "1" } but not viceversa
+ ASSERT_TRUE(shardKeyPatternHashed2_1.isExtendedBy(shardKeyPatternHashed3_1));
+ ASSERT_FALSE(shardKeyPatternHashed3_1.isExtendedBy(shardKeyPatternHashed2_1));
+}
+
} // namespace
} // namespace mongo