summaryrefslogtreecommitdiff
path: root/jstests/sharding/shard_keys_with_dollar_sign.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/sharding/shard_keys_with_dollar_sign.js')
-rw-r--r--jstests/sharding/shard_keys_with_dollar_sign.js75
1 files changed, 75 insertions, 0 deletions
diff --git a/jstests/sharding/shard_keys_with_dollar_sign.js b/jstests/sharding/shard_keys_with_dollar_sign.js
new file mode 100644
index 00000000000..c7fbbc73be5
--- /dev/null
+++ b/jstests/sharding/shard_keys_with_dollar_sign.js
@@ -0,0 +1,75 @@
+/**
+ * Tests that the shardCollection command and reshardCollection command correctly reject a shard key
+ * that has a field name that starts with '$' or contains parts that start with '$' unless the part
+ * is a DBRef (i.e. is equal to '$id', '$db' or '$ref').
+ */
+(function() {
+"use strict";
+
+const criticalSectionTimeoutMS = 24 * 60 * 60 * 1000; // 1 day
+const st = new ShardingTest({
+ shards: 1,
+ other: {
+ // Avoid spurious failures with small 'ReshardingCriticalSectionTimeout' values being set.
+ configOptions:
+ {setParameter: {reshardingCriticalSectionTimeoutMillis: criticalSectionTimeoutMS}}
+ }
+});
+
+const dbName = "testDb";
+const ns0 = dbName + ".testColl0";
+const ns1 = dbName + ".testColl1";
+const ns2 = dbName + ".testColl2";
+const db = st.s.getDB(dbName);
+
+function testValidation(key, {isValidIndexKey, isValidShardKey}) {
+ jsTest.log(`Testing ${tojson({key, isValidIndexKey, isValidShardKey})}`);
+ assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
+ st.ensurePrimaryShard(dbName, st.shard0.name);
+
+ const createIndexRes = db.getCollection(ns0).createIndex(key);
+ if (isValidIndexKey) {
+ assert.commandWorked(createIndexRes);
+ } else {
+ assert.commandFailedWithCode(createIndexRes, ErrorCodes.CannotCreateIndex);
+ }
+
+ const shardCollectionRes = st.s.adminCommand({shardCollection: ns1, key});
+ if (isValidShardKey) {
+ assert.commandWorked(shardCollectionRes);
+ } else {
+ assert.commandFailedWithCode(shardCollectionRes, ErrorCodes.BadValue);
+ }
+
+ assert.commandWorked(st.s.adminCommand({shardCollection: ns2, key: {_id: 1}}));
+ const reshardCollectionRes = st.s.adminCommand({reshardCollection: ns2, key});
+ if (isValidShardKey) {
+ assert.commandWorked(reshardCollectionRes);
+ } else {
+ assert.commandFailedWithCode(reshardCollectionRes, ErrorCodes.BadValue);
+ }
+
+ assert.commandWorked(db.dropDatabase());
+}
+
+testValidation({"$x": 1}, {isValidIndexKey: false, isValidShardKey: false});
+testValidation({"x.$y": 1}, {isValidIndexKey: false, isValidShardKey: false});
+testValidation({"$**": 1}, {isValidIndexKey: true, isValidShardKey: false});
+testValidation({"x.$**": 1}, {isValidIndexKey: true, isValidShardKey: false});
+testValidation({"$": 1}, {isValidIndexKey: false, isValidShardKey: false});
+
+testValidation({"x$": 1}, {isValidIndexKey: true, isValidShardKey: true});
+testValidation({"x$.y": 1}, {isValidIndexKey: true, isValidShardKey: true});
+testValidation({"x.y$": 1}, {isValidIndexKey: true, isValidShardKey: true});
+
+// Verify that a shard key can have a field that contains a DBRef as long as the field itself
+// does not start with '$'.
+testValidation({"$id": 1}, {isValidIndexKey: false, isValidShardKey: false});
+testValidation({"$db": 1}, {isValidIndexKey: false, isValidShardKey: false});
+testValidation({"$ref": 1}, {isValidIndexKey: false, isValidShardKey: false});
+testValidation({"x.$id": 1}, {isValidIndexKey: true, isValidShardKey: true});
+testValidation({"x.$db": 1}, {isValidIndexKey: true, isValidShardKey: true});
+testValidation({"x.$ref": 1}, {isValidIndexKey: true, isValidShardKey: true});
+
+st.stop();
+})();