diff options
Diffstat (limited to 'jstests/sharding/query')
10 files changed, 14 insertions, 376 deletions
diff --git a/jstests/sharding/query/agg_explain_fmt.js b/jstests/sharding/query/agg_explain_fmt.js index a1049e6f937..b11381a63d1 100644 --- a/jstests/sharding/query/agg_explain_fmt.js +++ b/jstests/sharding/query/agg_explain_fmt.js @@ -59,6 +59,7 @@ assert.eq(mergeCursors.nss, "test.agg_explain_fmt", mergeCursors); // This test manually sets collection and db at the top. assert.eq(mergeCursors.allowPartialResults, false, mergeCursors); +assert.eq(mergeCursors.recordRemoteOpWaitTime, false, mergeCursors); // Do a sharded explain from a mongod, not mongos, to ensure that it does not have a // SHARDING_FILTER stage."); diff --git a/jstests/sharding/query/aggregation_currentop.js b/jstests/sharding/query/aggregation_currentop.js index 207d93b42f2..58d63128329 100644 --- a/jstests/sharding/query/aggregation_currentop.js +++ b/jstests/sharding/query/aggregation_currentop.js @@ -13,7 +13,7 @@ * applicable. * * This test requires replica set configuration and user credentials to persist across a restart. - * @tags: [requires_persistence, uses_transactions, uses_prepare_transaction, requires_fcv_60] + * @tags: [requires_persistence, uses_transactions, uses_prepare_transaction] */ // Restarts cause issues with authentication for awaiting replication. @@ -411,8 +411,7 @@ function runCommonTests(conn, curOpSpec) { explain: true })); - let expectedStages = - [{$currentOp: {idleConnections: true, allUsers: false}}, {$match: {desc: {$eq: "test"}}}]; + let expectedStages = [{$currentOp: {idleConnections: true}}, {$match: {desc: {$eq: "test"}}}]; if (isRemoteShardCurOp) { assert.docEq(explainPlan.splitPipeline.shardsPart, expectedStages); diff --git a/jstests/sharding/query/delete_with_partial_shard_key.js b/jstests/sharding/query/delete_with_partial_shard_key.js deleted file mode 100644 index 8fb85a40900..00000000000 --- a/jstests/sharding/query/delete_with_partial_shard_key.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Tests that delete queries that are not an exact match on shard key and target only a single shard - * work. - */ - -(function() { -'use strict'; - -load('jstests/sharding/libs/with_partial_shard_key_util.js'); - -const st = new ShardingTest({shards: 2}); - -// Setup the test by creating two chunks: -// 1. The first chunk has documents with "a" from [min, 2) and is on shard0. -// 2. The second chunk has documents with "a" from [2, max) and is on shard1. -const dbName = "test"; -const coll = "sharded_coll"; -const ns = dbName + "." + coll; -const db = st.getDB(dbName); -const docsToInsert = [{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 1}, {a: 999, b: 1}]; -assert.commandWorked(st.s0.adminCommand({enableSharding: dbName})); -assert.commandWorked(st.s0.adminCommand({shardcollection: ns, key: {a: 1, b: 1}})); -db.sharded_coll.insert(docsToInsert); -splitAndMoveChunks(st, - {a: 2, b: 1} /* split point */, - {a: 1, b: 1} /* move chunk containing doc to shard0 */, - {a: 3, b: 1} /* move chunk containing doc to shard1 */); - -// deleteOne query without the full shard key and only one shard targeted should succeed. -assert.eq(db.sharded_coll.count({a: 999}), 1); -let cmdObj = {delete: coll, deletes: [{q: {a: 999}, limit: 1}]}; -assert.commandWorked(db.runCommand(cmdObj)); -assert.eq(db.sharded_coll.count({a: 999}), 0); -assertExplainTargetsCorrectShard(db, cmdObj, st.shard1.shardName); - -// deleteOne query without the full shard key and multiple shards targeted should fail. -cmdObj = { - delete: coll, - deletes: [{q: {a: {$gt: 0}}, limit: 1}] -}; -assert.commandFailedWithCode(db.runCommand(cmdObj), ErrorCodes.ShardKeyNotFound); -assert.commandFailedWithCode(db.runCommand({explain: cmdObj}), ErrorCodes.ShardKeyNotFound); - -// deleteOne query without the shard key should fail (as this would requiring targeting more than -// one shard). -cmdObj = { - delete: coll, - deletes: [{q: {nonShardKey: 12345}, limit: 1}] -}; -assert.commandFailedWithCode(db.runCommand(cmdObj), ErrorCodes.ShardKeyNotFound); -assert.commandFailedWithCode(db.runCommand({explain: cmdObj}), ErrorCodes.ShardKeyNotFound); - -// deleteMany query that targets only one shard should work correctly. -assert.eq(db.sharded_coll.count({a: 1}), 1); -cmdObj = { - delete: coll, - deletes: [{q: {a: 1}, limit: 0}] -}; -assert.commandWorked(db.runCommand(cmdObj)); -assert.eq(db.sharded_coll.count({a: 1}), 0); -assert.eq(db.sharded_coll.count({a: {$gt: 0}}), 2); // Check that other documents were not deleted. -assertExplainTargetsCorrectShard(db, cmdObj, st.shard0.shardName); - -st.stop(); -})(); diff --git a/jstests/sharding/query/find_and_modify_with_partial_shard_key.js b/jstests/sharding/query/find_and_modify_with_partial_shard_key.js deleted file mode 100644 index e0a0bb1b3f9..00000000000 --- a/jstests/sharding/query/find_and_modify_with_partial_shard_key.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Tests that findAndModify queries that are not an exact match on shard key and target only a - * single shard work. - */ - -(function() { -'use strict'; - -load('jstests/sharding/libs/with_partial_shard_key_util.js'); - -const st = new ShardingTest({shards: 2}); - -// Setup the test by creating two chunks: -// 1. The first chunk has documents with "a" from [min, 2) and is on shard0. -// 2. The second chunk has documents with "a" from [2, max) and is on shard1. -const dbName = "test"; -const coll = "sharded_coll"; -const ns = dbName + "." + coll; -const db = st.getDB(dbName); -const docsToInsert = [{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 1}, {a: 999, b: 1}]; -assert.commandWorked(st.s0.adminCommand({enableSharding: dbName})); -assert.commandWorked(st.s0.adminCommand({shardcollection: ns, key: {a: 1, b: 1}})); -db.sharded_coll.insert(docsToInsert); -splitAndMoveChunks(st, - {a: 2, b: 1} /* split point */, - {a: 1, b: 1} /* move chunk containing doc to shard0 */, - {a: 3, b: 1} /* move chunk containing doc to shard1 */); - -// Query without the full shard key and only one shard targeted should succeed. -assert.eq(db.sharded_coll.count({a: 1, name: "bob"}), 0); -let cmdObj = {findAndModify: coll, query: {a: 1}, update: {$set: {name: "bob"}}}; -assert.commandWorked(db.runCommand(cmdObj)); -assert.eq(db.sharded_coll.count({a: 1, name: "bob"}), 1); -assertExplainTargetsCorrectShard(db, cmdObj, st.shard0.shardName); - -// Query without the full shard key and multiple shards targeted should fail. -cmdObj = { - findAndModify: coll, - query: {a: {$gt: 0}}, - update: {$set: {name: "bob"}} -}; -assert.commandFailedWithCode(db.runCommand(cmdObj), ErrorCodes.ShardKeyNotFound); -assert.commandFailedWithCode(db.runCommand({explain: cmdObj}), ErrorCodes.ShardKeyNotFound); - -// Query without the shard key should fail (as this would requiring targeting more than one shard). -cmdObj = { - findAndModify: coll, - query: {c: "3"}, - update: {$set: {name: "bob"}} -}; -assert.commandFailedWithCode(db.runCommand(cmdObj), ErrorCodes.ShardKeyNotFound); -assert.commandFailedWithCode(db.runCommand({explain: cmdObj}), ErrorCodes.ShardKeyNotFound); - -st.stop(); -})(); diff --git a/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js b/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js index 1bc05f59555..c3924654a74 100644 --- a/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js +++ b/jstests/sharding/query/lookup_graph_lookup_foreign_becomes_sharded.js @@ -225,14 +225,14 @@ for (let testCase of testCases) { const newStaleConfigErrorCount = assert.commandWorked(primaryDB.runCommand({serverStatus: 1})) .shardingStatistics.countStaleConfigErrors; -// ... and a single StaleConfig error for the foreign namespace. Note that the 'ns' field of the +// ... and a single StaleConfig exception for the foreign namespace. Note that the 'ns' field of the // profiler entry is the source collection in both cases, because the $lookup's parent aggregation // produces the profiler entry, and it is always running on the source collection. // TODO SERVER-60018: When the feature flag is removed, remove the check and ensure the results are // expected. if (!isShardedLookupEnabled) { - // Both in the classic lookup and the SBE lookup, StaleConfig error happens. In the classic - // lookup, profiling can properly report the StaleConfig of the foreign collection. + // Both in the classic lookup and the SBE lookup, 'StaleConfig' error happens. In the classic + // lookup, profiling can properly report the 'StaleConfig' of the foreign collection. // // On the other hand, in the SBE lookup, profiling fails to report the error because the // profiling level is not set up properly according to the configured profiling level in case of diff --git a/jstests/sharding/query/lookup_mongod_unaware.js b/jstests/sharding/query/lookup_mongod_unaware.js index 35cc9d920cb..41e5f23047b 100644 --- a/jstests/sharding/query/lookup_mongod_unaware.js +++ b/jstests/sharding/query/lookup_mongod_unaware.js @@ -6,9 +6,8 @@ * We restart a mongod to cause it to forget that a collection was sharded. When restarted, we * expect it to still have all the previous data. * - * // TODO (SERVER-74380): Remove requires_fcv_70 once SERVER-74380 has been backported to v6.0 * @tags: [ - * requires_persistence, + * requires_persistence * ] * */ @@ -19,7 +18,7 @@ load("jstests/noPassthrough/libs/server_parameter_helpers.js"); // For setParam load("jstests/libs/discover_topology.js"); // For findDataBearingNodes. // Restarts the primary shard and ensures that it believes both collections are unsharded. -function restartPrimaryShard(rs, ...expectedCollections) { +function restartPrimaryShard(rs, localColl, foreignColl) { // Returns true if the shard is aware that the collection is sharded. function hasRoutingInfoForNs(shardConn, coll) { const res = shardConn.adminCommand({getShardVersion: coll, fullMetadata: true}); @@ -29,11 +28,8 @@ function restartPrimaryShard(rs, ...expectedCollections) { rs.restart(0); rs.awaitSecondaryNodes(); - - expectedCollections.forEach(function(coll) { - assert(!hasRoutingInfoForNs(rs.getPrimary(), coll.getFullName()), - 'Shard role not cleared for ' + coll.getFullName()); - }); + assert(!hasRoutingInfoForNs(rs.getPrimary(), localColl.getFullName())); + assert(!hasRoutingInfoForNs(rs.getPrimary(), foreignColl.getFullName())); } // Disable checking for index consistency to ensure that the config server doesn't trigger a @@ -174,55 +170,5 @@ assert.eq(mongos0LocalColl.aggregate(pipeline).toArray(), expectedResults); restartPrimaryShard(st.rs0, mongos0LocalColl, mongos0ForeignColl); assert.eq(mongos1LocalColl.aggregate(pipeline).toArray(), expectedResults); -// -// Test two-level $lookup with a stale shard handles the shard role recovery case. -// -jsTest.log("Running two-level $lookup with a shard that needs recovery"); - -assert.commandWorked(st.s0.adminCommand({enableSharding: 'D'})); -st.ensurePrimaryShard('D', st.shard0.shardName); - -const D = st.s0.getDB('D'); - -assert.commandWorked(D.A.insert({Key: 1, Value: 1})); -assert.commandWorked(D.B.insert({Key: 1, Value: 1})); -assert.commandWorked(D.C.insert({Key: 1, Value: 1})); -assert.commandWorked(D.D.insert({Key: 1, Value: 1})); - -const aggPipeline = [{ - $lookup: { - from: 'B', - localField: 'Key', - foreignField: 'Value', - as: 'Joined', - pipeline: [ - { - $lookup: { - from: 'C', - localField: 'Key', - foreignField: 'Value', - as: 'Joined', - } - }, - { - $lookup: { - from: 'D', - localField: 'Key', - foreignField: 'Value', - as: 'Joined', - } - }, - ], - } -}]; - -const resultBefore = D.A.aggregate(aggPipeline).toArray(); - -// Restarting the shard primary in order for the shard role's cache to be cleared -restartPrimaryShard(st.rs0, D.A, D.B, D.C, D.D); - -const resultAfter = D.A.aggregate(aggPipeline).toArray(); -assert.eq(resultBefore, resultAfter, "Before and after results do not match"); - st.stop(); })(); diff --git a/jstests/sharding/query/merge_nondefault_read_concern.js b/jstests/sharding/query/merge_nondefault_read_concern.js deleted file mode 100644 index 70df9207bd8..00000000000 --- a/jstests/sharding/query/merge_nondefault_read_concern.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Tests that $merge doesn't fail when a non-default readConcern is - * set on the session. - * @tags: [requires_fcv_71] - */ -(function() { -"use strict"; - -load("jstests/aggregation/extras/merge_helpers.js"); - -const st = new ShardingTest({shards: 2, rs: {nodes: 1}}); - -const mongosDB = st.s0.getDB("merge_nondefault_read_concern"); -const source = mongosDB["source"]; -const target = mongosDB["target"]; - -assert.commandWorked(mongosDB.adminCommand({enableSharding: mongosDB.getName()})); - -const baseMergeCommand = { - aggregate: "source", - pipeline: - [{$merge: {into: "target", on: "_id", whenMatched: "replace", whenNotMatched: "insert"}}], - cursor: {}, -}; - -// Test with command level override. -var withReadConcern = baseMergeCommand; -withReadConcern.readConcern = { - level: "majority" -}; -assert.commandWorked(mongosDB.runCommand(withReadConcern)); - -// Test with global override. -assert.commandWorked( - mongosDB.adminCommand({"setDefaultRWConcern": 1, "defaultReadConcern": {level: "majority"}})); -assert.commandWorked(mongosDB.runCommand(baseMergeCommand)); - -st.stop(); -}()); diff --git a/jstests/sharding/query/merge_write_concern.js b/jstests/sharding/query/merge_write_concern.js index a29c8b7e6b8..1aac599f0f8 100644 --- a/jstests/sharding/query/merge_write_concern.js +++ b/jstests/sharding/query/merge_write_concern.js @@ -17,21 +17,12 @@ assert.commandWorked(mongosDB.adminCommand({enableSharding: mongosDB.getName()}) st.ensurePrimaryShard(mongosDB.getName(), st.shard0.shardName); function testWriteConcernError(rs) { - // Split the target collection at {_id: 10} so that there'll be doc $merge-ed to both shards. - if (FixtureHelpers.isSharded(target)) { - mongosDB.adminCommand({split: target.getFullName(), middle: {_id: 10}}); - } - // Make sure that there are only 2 nodes up so w:3 writes will always time out. const stoppedSecondary = rs.getSecondary(); rs.stop(stoppedSecondary); // Test that $merge correctly returns a WC error. withEachMergeMode(({whenMatchedMode, whenNotMatchedMode}) => { - // When either mode is "fail", a different error rather than WC error is thrown. - if (whenMatchedMode === "fail" || whenNotMatchedMode === "fail") { - return; - } const res = mongosDB.runCommand({ aggregate: "source", pipeline: [{ @@ -45,24 +36,13 @@ function testWriteConcernError(rs) { cursor: {}, }); - jsTestLog("Testing Mode: " + tojson(whenMatchedMode) + tojson(whenNotMatchedMode)); - jsTestLog("Target collection after $merge: " + tojson(target.find().toArray())); - - let oplogEntries = shard0.getPrimary() - .getDB("local") - .oplog.rs.find({"ns": {$regex: "merge_write_concern.*"}}) - .toArray(); - jsTestLog("Shard0 oplog entries: " + tojson(oplogEntries)); - oplogEntries = shard1.getPrimary() - .getDB("local") - .oplog.rs.find({"ns": {$regex: "merge_write_concern.*"}}) - .toArray(); - jsTestLog("Shard1 oplog entries: " + tojson(oplogEntries)); - // $merge writeConcern errors are handled differently from normal writeConcern // errors. Rather than returing ok:1 and a WriteConcernError, the entire operation // fails. - assert.commandFailedWithCode(res, ErrorCodes.WriteConcernFailed); + assert.commandFailedWithCode(res, + whenNotMatchedMode == "fail" + ? [13113, ErrorCodes.WriteConcernFailed] + : ErrorCodes.WriteConcernFailed); assert.commandWorked(target.remove({})); }); diff --git a/jstests/sharding/query/metadata_removal.js b/jstests/sharding/query/metadata_removal.js deleted file mode 100644 index 7caba6433bc..00000000000 --- a/jstests/sharding/query/metadata_removal.js +++ /dev/null @@ -1,46 +0,0 @@ -// Ensure that metadata fields (and only metadata) are removed before documents are returned to -// customers. As we can't insert documents with metadata, this test focuses on queries that might -// inject metadata when communication results to mongos for merging. In addition, we want to ensure -// that other fields beginning with a '$' are not modified before returning them to customers. -// @tags: [ -// requires_fcv_60 -// ] - -(function() { -"use strict"; - -function runTest(coll, keyword) { - const document = ({_id: 5, x: 1, $set: {$inc: {x: 5}}}); - assert.commandWorked(coll.insert(document)); - - // Leaves $set intact without shard merging. - assert.eq([document], coll.find().hint({$natural: 1}).toArray()); - assert.eq([document], coll.find().hint({_id: 1}).toArray()); - - // Leaves $set intact when shard merging on agg query. - const docWithY = ({_id: 5, x: 1, $set: {$inc: {x: 5}}, y: 1}); - assert.eq([docWithY], coll.aggregate([{$addFields: {y: 1}}]).toArray()); - - // Leaves $set intact when shard merging on sort query. - assert.eq([document], coll.find().sort({_id: 1}).toArray()); - - // Leaves added fields intact when user adds $ prefixed field in an agg pipeline. - const docWithDollarY = ({_id: 5, x: 1, $set: {$inc: {x: 5}}, $y: 1}); - assert.eq( - [docWithDollarY], - coll.aggregate( - [{$replaceWith: {$setField: {field: {$literal: "$y"}, input: "$$ROOT", value: 1}}}]) - .toArray()); -} - -const st = new ShardingTest({shards: 2}); -try { - assert.commandWorked(st.s0.adminCommand({enableSharding: 'test'})); - st.ensurePrimaryShard('test', st.shard1.shardName); - assert.commandWorked(st.s0.adminCommand({shardCollection: 'test.coll', key: {x: 'hashed'}})); - - runTest(st.getDB("test").coll); -} finally { - st.stop(); -} -})(); diff --git a/jstests/sharding/query/shard_refuses_cursor_ownership.js b/jstests/sharding/query/shard_refuses_cursor_ownership.js deleted file mode 100644 index 30e6e88d896..00000000000 --- a/jstests/sharding/query/shard_refuses_cursor_ownership.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * This test runs and unsharded $out query which results in mongos setting up a cursor and giving - * it to a shard to complete. mongos assumes the shard will kill the cursor, but if a shard doesn't - * accept ownership of the cursor then previously no one would kill it. this test ensures mongos - * will kill the cursor if a shard doesn't accept ownership. - * @tags: [ - * ] - */ -(function() { -"use strict"; - -load("jstests/libs/fail_point_util.js"); -load("jstests/libs/parallel_shell_helpers.js"); - -const st = new ShardingTest({shards: 2}); - -const dbName = jsTestName(); -const collName = "foo"; -const ns = dbName + "." + collName; - -let db = st.s.getDB(dbName); -assert.commandWorked(db.dropDatabase()); -let coll = db[collName]; - -st.shardColl(collName, {x: 1}, {x: 0}, {x: 1}, dbName, true); - -assert.commandWorked(coll.insert([{x: -2}, {x: -1}, {x: 1}, {x: 2}])); - -const primary = st.getPrimaryShard(dbName); -const other = st.getOther(st.getPrimaryShard(dbName)); - -// Start an aggregation that requires merging on a shard. Let it run until the shard cursors have -// been established but make it hang right before opening the merge cursor. -let shardedAggregateHangBeforeDispatchMergingPipelineFP = - configureFailPoint(st.s, "shardedAggregateHangBeforeDispatchMergingPipeline"); -let awaitAggregationShell = startParallelShell( - funWithArgs((dbName, collName) => { - assert.eq( - 0, db.getSiblingDB(dbName)[collName].aggregate([{$out: collName + ".out"}]).itcount()); - }, dbName, collName), st.s.port); -shardedAggregateHangBeforeDispatchMergingPipelineFP.wait(); - -// Start a chunk migration, let it run until it enters the critical section. -let hangBeforePostMigrationCommitRefresh = - configureFailPoint(primary, "hangBeforePostMigrationCommitRefresh"); -let awaitMoveChunkShell = startParallelShell( - funWithArgs((recipientShard, ns) => { - assert.commandWorked(db.adminCommand({moveChunk: ns, find: {x: -1}, to: recipientShard})); - }, other.shardName, ns), st.s.port); -hangBeforePostMigrationCommitRefresh.wait(); - -// Let the aggregation continue and try to establish the merge cursor (it will first fail because -// the shard is in the critical section. Mongos will transparently retry). -shardedAggregateHangBeforeDispatchMergingPipelineFP.off(); - -// Let the migration exit the critical section and complete. -hangBeforePostMigrationCommitRefresh.off(); - -// The aggregation will be able to complete now. -awaitAggregationShell(); - -awaitMoveChunkShell(); - -// Did any cursor leak? -const idleCursors = primary.getDB("admin") - .aggregate([ - {$currentOp: {idleCursors: true, allUsers: true}}, - {$match: {type: "idleCursor", ns: ns}} - ]) - .toArray(); -assert.eq(0, idleCursors.length, "Found idle cursors: " + tojson(idleCursors)); - -// Check that range deletions can be completed (if a cursor was left open, the range deletion would -// not finish). -assert.soon( - () => { - return primary.getDB("config")["rangeDeletions"].find().itcount() === 0; - }, - "Range deletion tasks did not finish: + " + - tojson(primary.getDB("config")["rangeDeletions"].find().toArray())); - -st.stop(); -})(); |
