summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Golfieri <enrico.golfieri@mongodb.com>2022-09-07 14:28:24 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-12 09:31:21 +0000
commit80e78ce7159c4adf6a0332eda578c8d770a76ba0 (patch)
treea954a201a4b6d727f6737ceae6fc564bde705c3a
parent3bf0d522db3017a344e5f093706539e97659897b (diff)
downloadmongo-80e78ce7159c4adf6a0332eda578c8d770a76ba0.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 c8fb1b7a84c..7bfb9c88237 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"
@@ -288,7 +289,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 2965b5d6222..b7c2a3e24b1 100644
--- a/src/mongo/s/shard_key_pattern_test.cpp
+++ b/src/mongo/s/shard_key_pattern_test.cpp
@@ -1016,5 +1016,83 @@ TEST_F(ShardKeyPatternTest, ExtractShardKeyFromDocumentKey_Hashed) {
BSONObj());
}
+TEST_F(ShardKeyPatternTest, 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