summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Banala <arun.banala@mongodb.com>2023-01-21 12:36:00 -0800
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-01-23 21:02:30 +0000
commit9642e21ac80ca1b1b019b56a57b21b487107ad3f (patch)
tree6d05ccd91f870b382b132e917c3ec443d65c3340
parent52e0ccbe64eb8f5cebe1c2446dfffbba0b784a5c (diff)
downloadmongo-9642e21ac80ca1b1b019b56a57b21b487107ad3f.tar.gz
Revert "SERVER-72416 Find and findAndModify commands' ExpressionContext should inherit collection level collation"
This reverts commit aed1cb6469f207e7e6ab053fdfb2c472b7b345ec.
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml2
-rw-r--r--buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml1
-rw-r--r--etc/backports_required_for_multiversion_tests.yml16
-rw-r--r--jstests/core/index_filter_collation.js2
-rw-r--r--jstests/core/or_to_in.js134
-rw-r--r--jstests/core/project_with_collation.js116
-rw-r--r--jstests/libs/parallelTester.js1
-rw-r--r--src/mongo/db/commands/find_cmd.cpp23
-rw-r--r--src/mongo/db/ops/parsed_delete.cpp8
-rw-r--r--src/mongo/db/ops/parsed_delete.h2
-rw-r--r--src/mongo/db/query/get_executor.cpp7
16 files changed, 51 insertions, 266 deletions
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml
index 4a7cbc7ff47..79a61f3aab6 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml
@@ -24,7 +24,6 @@ selector:
- jstests/core/find_and_modify.js
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_server6865.js
- - jstests/core/project_with_collation.js
# Stepdown commands during fsync lock will fail.
- jstests/core/currentop.js
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml
index 4c993a6f8a1..026f7c4b4df 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml
@@ -228,7 +228,6 @@ selector:
- jstests/core/find_and_modify.js
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_server6865.js
- - jstests/core/project_with_collation.js
# Does not support tojson of command objects.
- jstests/core/SERVER-23626.js
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml
index c69bc7b93ca..e17dcef77ed 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml
@@ -33,7 +33,6 @@ selector:
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_pipeline_update.js
- jstests/core/find_and_modify_server6865.js
- - jstests/core/project_with_collation.js
# These test run commands using legacy queries, which are not supported on sessions.
- jstests/core/comment_field.js
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml
index 2ea8498e252..e1ed9b2ccdc 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml
@@ -34,7 +34,6 @@ selector:
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_pipeline_update.js
- jstests/core/find_and_modify_server6865.js
- - jstests/core/project_with_collation.js
# These test run commands using legacy queries, which are not supported on sessions.
- jstests/core/comment_field.js
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml
index 28c13b41e1c..e8aca959007 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml
@@ -24,8 +24,6 @@ selector:
- jstests/core/find_and_modify.js
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_server6865.js
- - jstests/core/project_with_collation.js
-
# Stepdown commands during fsync lock will fail.
- jstests/core/currentop.js
diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml
index 779d1cef810..244143c25ee 100644
--- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml
@@ -32,7 +32,6 @@ selector:
- jstests/core/find_and_modify_pipeline_update.js
- jstests/core/find_and_modify_server6865.js
- jstests/core/fts_find_and_modify.js
- - jstests/core/project_with_collation.js
# These tests rely on the assumption that an update command is run only once.
- jstests/core/find_and_modify_metrics.js
diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
index 3fa9438991e..1493f5626ba 100644
--- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
@@ -25,7 +25,6 @@ selector:
- jstests/core/find_and_modify2.js
- jstests/core/find_and_modify_server6865.js
- jstests/core/fts_find_and_modify.js
- - jstests/core/project_with_collation.js
# Stepdown commands during fsync lock will fail.
- jstests/core/currentop.js
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml
index b264e0e45b5..3a122e489b9 100644
--- a/etc/backports_required_for_multiversion_tests.yml
+++ b/etc/backports_required_for_multiversion_tests.yml
@@ -88,14 +88,6 @@ last-continuous:
ticket: SERVER-68628
- test_file: jstests/sharding/move_chunk_interrupt_postimage.js
ticket: SERVER-68728
- - test_file: jstests/core/project_with_collation.js
- ticket: SERVER-72416
- - test_file: jstests/core/collation.js
- ticket: SERVER-72416
- - test_file: jstests/core/or_to_in.js
- ticket: SERVER-72416
- - test_file: jstests/core/index_filter_collation.js
- ticket: SERVER-72416
suites:
change_streams_multiversion_passthrough: null
change_streams_sharded_collections_multiversion_passthrough: null
@@ -281,14 +273,6 @@ last-lts:
ticket: SERVER-68628
- test_file: jstests/sharding/move_chunk_interrupt_postimage.js
ticket: SERVER-68728
- - test_file: jstests/core/project_with_collation.js
- ticket: SERVER-72416
- - test_file: jstests/core/collation.js
- ticket: SERVER-72416
- - test_file: jstests/core/or_to_in.js
- ticket: SERVER-72416
- - test_file: jstests/core/index_filter_collation.js
- ticket: SERVER-72416
suites:
change_streams_multiversion_passthrough: null
change_streams_sharded_collections_multiversion_passthrough: null
diff --git a/jstests/core/index_filter_collation.js b/jstests/core/index_filter_collation.js
index 9a4232a0480..74ec64f3b3c 100644
--- a/jstests/core/index_filter_collation.js
+++ b/jstests/core/index_filter_collation.js
@@ -77,7 +77,7 @@ function assertIsIxScanOnIndex(winningPlan, keyPattern) {
// Run the queries and be sure the correct indexes are used.
let explain = coll.find({x: 3}).explain();
checkIndexFilterSet(explain, true);
-assertIsIxScanOnIndex(getWinningPlan(explain.queryPlanner), {x: 1});
+assertIsIxScanOnIndex(getWinningPlan(explain.queryPlanner), {x: 1, y: 1});
// Run the queries and be sure the correct indexes are used.
explain = coll.find({x: 3}).collation(caseInsensitive).explain();
diff --git a/jstests/core/or_to_in.js b/jstests/core/or_to_in.js
index 0c199c49a21..9aed36237b7 100644
--- a/jstests/core/or_to_in.js
+++ b/jstests/core/or_to_in.js
@@ -26,24 +26,18 @@ function compareValues(v1, v2) {
}
// Check that 'expectedQuery' and 'actualQuery' have the same plans, and produce the same result.
-function assertEquivPlanAndResult(expectedQuery, actualQuery, supportWithCollation) {
+function assertEquivPlanAndResult(expectedQuery, actualQuery) {
const expectedExplain = coll.find(expectedQuery).explain("queryPlanner");
const actualExplain = coll.find(actualQuery).explain("queryPlanner");
// The queries must be rewritten into the same form.
- assert.docEq(expectedExplain.queryPlanner.parsedQuery, actualExplain.queryPlanner.parsedQuery);
+ assert.docEq(expectedExplain.parsedQuery, actualExplain.parsedQuery);
- // We are always running these queries to ensure a server crash is not triggered.
- // TODO SERVER-72450: Add appropriate assertions for the output.
- const expectedExplainCollation =
+ // Check if the test queries produce the same plans with collations
+ const expectedExplainColln =
coll.find(expectedQuery).sort({f1: 1}).collation({locale: 'en_US'}).explain("queryPlanner");
- const actualExplainCollation =
+ const actualExplainColln =
coll.find(actualQuery).sort({f1: 1}).collation({locale: 'en_US'}).explain("queryPlanner");
-
- if (supportWithCollation) {
- // Check if the test queries produce the same plans with collations.
- assert.docEq(expectedExplainCollation.queryPlanner.parsedQuery,
- actualExplainCollation.queryPlanner.parsedQuery);
- }
+ assert.docEq(expectedExplainColln.parsedQuery, actualExplainColln.parsedQuery);
// Make sure both queries have the same access plan.
const expectedPlan = getWinningPlan(expectedExplain.queryPlanner);
@@ -54,13 +48,12 @@ function assertEquivPlanAndResult(expectedQuery, actualQuery, supportWithCollati
const actualRes = coll.find(actualQuery).toArray();
assert(arrayEq(expectedRes, actualRes, false, compareValues),
`expected=${expectedRes}, actual=${actualRes}`);
-
// also with collation
- const expectedResCollation =
+ const expectedResColln =
coll.find(expectedQuery).sort({f1: 1}).collation({locale: 'en_US'}).toArray();
- const actualResCollation =
+ const actualResColln =
coll.find(actualQuery).sort({f1: 1}).collation({locale: 'en_US'}).toArray();
- assert(arrayEq(expectedResCollation, actualResCollation, false, compareValues),
+ assert(arrayEq(expectedResColln, actualResColln, false, compareValues),
`expected=${expectedRes}, actual=${actualRes}`);
}
@@ -98,71 +91,33 @@ assert.commandWorked(coll.insert(data));
// Pairs of queries where the first one is expressed via OR (which is supposed to be
// rewritten as IN), and the second one is an equivalent query using IN.
-//
-// The third element of the array is optional, if present, implies that the rewrite is not
-// supported when there is a collation involved.
-//
-// TODO SERVER-72450: Remove or update this logic related to collation, and enforce stronger
-// assertions.
const positiveTestQueries = [
- {actualQuery: {$or: [{f1: 5}, {f1: 3}, {f1: 7}]}, expectedQuery: {f1: {$in: [7, 3, 5]}}},
- {
- actualQuery: {$or: [{f1: {$eq: 5}}, {f1: {$eq: 3}}, {f1: {$eq: 7}}]},
- expectedQuery: {f1: {$in: [7, 3, 5]}}
- },
- {
- actualQuery: {$or: [{f1: 42}, {f1: NaN}, {f1: 99}]},
- expectedQuery: {f1: {$in: [42, NaN, 99]}}
- },
- {
- actualQuery: {$or: [{f1: /^x/}, {f1: "ab"}]},
- expectedQuery: {f1: {$in: [/^x/, "ab"]}},
- cannotRewriteWithCollation: true
- },
- {
- actualQuery: {$or: [{f1: /^x/}, {f1: "^a"}]},
- expectedQuery: {f1: {$in: [/^x/, "^a"]}},
- cannotRewriteWithCollation: true
- },
- {
- actualQuery: {$or: [{f1: 42}, {f1: null}, {f1: 99}]},
- expectedQuery: {f1: {$in: [42, 99, null]}}
- },
- {
- actualQuery: {$or: [{f1: 1}, {f2: 9}, {f1: 99}]},
- expectedQuery: {$or: [{f2: 9}, {f1: {$in: [1, 99]}}]}
- },
- {
- actualQuery: {$or: [{f1: {$regex: /^x/}}, {f1: {$regex: /ab/}}]},
- expectedQuery: {f1: {$in: [/^x/, /ab/]}}
- },
- {
- actualQuery:
- {$and: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$and: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
- },
- {
- actualQuery:
- {$or: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$or: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
- },
- {
- actualQuery:
- {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
- expectedQuery: {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {f1: {$in: [1, 2, 3]}}]},
- },
- {
- actualQuery: {$or: [{f2: [32, 52]}, {f2: [42, [13, 11]]}]},
- expectedQuery: {f2: {$in: [[32, 52], [42, [13, 11]]]}}
- },
- {actualQuery: {$or: [{f2: 52}, {f2: 13}]}, expectedQuery: {f2: {$in: [52, 13]}}},
- {actualQuery: {$or: [{f2: [11]}, {f2: [23]}]}, expectedQuery: {f2: {$in: [[11], [23]]}}},
- {actualQuery: {$or: [{f1: 42}, {f1: null}]}, expectedQuery: {f1: {$in: [42, null]}}},
- {
- actualQuery: {$or: [{f1: "a"}, {f1: "b"}, {f1: /c/}]},
- expectedQuery: {f1: {$in: ["a", "b", /c/]}},
- cannotRewriteWithCollation: true
- },
+ [{$or: [{f1: 5}, {f1: 3}, {f1: 7}]}, {f1: {$in: [7, 3, 5]}}],
+ [{$or: [{f1: {$eq: 5}}, {f1: {$eq: 3}}, {f1: {$eq: 7}}]}, {f1: {$in: [7, 3, 5]}}],
+ [{$or: [{f1: 42}, {f1: NaN}, {f1: 99}]}, {f1: {$in: [42, NaN, 99]}}],
+ [{$or: [{f1: /^x/}, {f1: "ab"}]}, {f1: {$in: [/^x/, "ab"]}}],
+ [{$or: [{f1: /^x/}, {f1: "^a"}]}, {f1: {$in: [/^x/, "^a"]}}],
+ [{$or: [{f1: 42}, {f1: null}, {f1: 99}]}, {f1: {$in: [42, 99, null]}}],
+ [{$or: [{f1: 1}, {f2: 9}, {f1: 99}]}, {$or: [{f2: 9}, {f1: {$in: [1, 99]}}]}],
+ [{$or: [{f1: {$regex: /^x/}}, {f1: {$regex: /ab/}}]}, {f1: {$in: [/^x/, /ab/]}}],
+ [
+ {$and: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$and: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
+ ],
+ [
+ {$or: [{$or: [{f1: 7}, {f1: 3}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$or: [{f1: {$in: [7, 3, 5]}}, {f1: {$in: [1, 2, 3]}}]}
+ ],
+ [
+ {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {$or: [{f1: 1}, {f1: 2}, {f1: 3}]}]},
+ {$or: [{$and: [{f1: 7}, {f2: 7}, {f1: 5}]}, {f1: {$in: [1, 2, 3]}}]},
+ ],
+ [{$or: [{f2: [32, 52]}, {f2: [42, [13, 11]]}]}, {f2: {$in: [[32, 52], [42, [13, 11]]]}}],
+ [{$or: [{f2: 52}, {f2: 13}]}, {f2: {$in: [52, 13]}}],
+ [{$or: [{f2: [11]}, {f2: [23]}]}, {f2: {$in: [[11], [23]]}}],
+ {$or: [{f1: 42}, {f1: null}]},
+ [{$or: [{f1: 42}, {f1: null}]}, {f1: {$in: [42, null]}}],
+ [{$or: [{f1: "a"}, {f1: "b"}, {f1: /c/}]}, {f1: {$in: ["a", "b", /c/]}}],
];
// These $or queries should not be rewritten into $in because of different semantics.
@@ -176,27 +131,22 @@ for (const query of negativeTestQueries) {
assertOrNotRewrittenToIn(query);
}
-function testOrToIn(queries, usesCollation) {
+function testOrToIn(queries) {
for (const queryPair of queries) {
- if (usesCollation && queryPair.cannotRewriteWithCollation) {
- continue;
- }
- assertEquivPlanAndResult(
- queryPair.actualQuery, queryPair.expectedQuery, !queryPair.cannotRewriteWithCollation);
+ assertEquivPlanAndResult(queryPair[0], queryPair[1]);
}
}
-testOrToIn(positiveTestQueries, false /* usesCollation */); // test without indexes
+testOrToIn(positiveTestQueries); // test without indexes
assert.commandWorked(coll.createIndex({f1: 1}));
-testOrToIn(positiveTestQueries, false /* usesCollation */); // single index
+testOrToIn(positiveTestQueries); // single index
assert.commandWorked(coll.createIndex({f2: 1}));
assert.commandWorked(coll.createIndex({f1: 1, f2: 1}));
-testOrToIn(positiveTestQueries,
- false /* usesCollation */); // three indexes, requires multiplanning
+testOrToIn(positiveTestQueries); // three indexes, requires multiplanning
// Test with a collection that has a collation, and that collation is the same as the query
// collation
@@ -204,12 +154,12 @@ coll.drop();
assert.commandWorked(db.createCollection("orToIn", {collation: {locale: 'en_US'}}));
coll = db.orToIn;
assert.commandWorked(coll.insert(data));
-testOrToIn(positiveTestQueries, true /* usesCollation */);
+testOrToIn(positiveTestQueries);
// Test with a collection that has a collation, and that collation is different from the query
// collation
coll.drop();
assert.commandWorked(db.createCollection("orToIn", {collation: {locale: 'de'}}));
coll = db.orToIn;
assert.commandWorked(coll.insert(data));
-testOrToIn(positiveTestQueries, true /* usesCollation */);
+testOrToIn(positiveTestQueries);
}());
diff --git a/jstests/core/project_with_collation.js b/jstests/core/project_with_collation.js
deleted file mode 100644
index f0fb2fd8e6a..00000000000
--- a/jstests/core/project_with_collation.js
+++ /dev/null
@@ -1,116 +0,0 @@
-// Tests to verify the behavior of find command's project in the presence of collation.
-//
-// @tags: [
-// assumes_no_implicit_collection_creation_after_drop,
-// requires_find_command,
-// ]
-
-(function() {
-'use strict';
-
-const collation = {
- locale: "en_US",
- strength: 2
-};
-const withCollationCollName = jsTestName() + "_collation";
-const noCollationCollName = jsTestName() + "_noCollation";
-
-function setupCollection(withCollation) {
- const insertCollName = withCollation ? withCollationCollName : noCollationCollName;
- db[insertCollName].drop();
- if (withCollation) {
- assert.commandWorked(db.createCollection(insertCollName, {collation: withCollation}));
- }
-
- const insertColl = db[insertCollName];
- assert.commandWorked(insertColl.insert(
- {_id: 0, str: "a", array: [{str: "b"}, {str: "A"}, {str: "B"}, {str: "a"}]}));
- assert.commandWorked(insertColl.insert({_id: 1, str: "a", elemMatch: [{str: "A"}, "ignored"]}));
- assert.commandWorked(insertColl.insert({_id: 2, str: "A", elemMatch: ["ignored", {str: "a"}]}));
- assert.commandWorked(insertColl.insert({_id: 3, str: "B"}));
-
- return insertColl;
-}
-
-function runQueryWithCollation(testColl, collationToUse) {
- let findCmd =
- testColl.find({str: 'A', elemMatch: {$elemMatch: {str: "a"}}}, {_id: 1, 'elemMatch.$': 1});
- if (collationToUse) {
- findCmd = findCmd.collation(collationToUse);
- }
- const elemMatchOutput = findCmd.toArray();
- assert.sameMembers(elemMatchOutput,
- [{_id: 1, elemMatch: [{str: "A"}]}, {_id: 2, elemMatch: [{str: "a"}]}]);
-
- const findAndUpdateOutput = testColl.findAndModify({
- query: {_id: 1, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- update: {$set: {updated: true}},
- collation: collationToUse
- });
- assert.docEq(findAndUpdateOutput, {_id: 1, elemMatch: [{str: "A"}]});
-
- const findAndRemoveOutput = testColl.findAndModify({
- query: {_id: 1, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- remove: true,
- collation: collationToUse,
- });
- assert.docEq(findAndRemoveOutput, {_id: 1, elemMatch: [{str: "A"}], updated: true});
-}
-
-// The output for the below two tests should not depend on the collection level collation.
-let collWithCollation = setupCollection({locale: "en_US"});
-runQueryWithCollation(collWithCollation, collation);
-
-let noCollationColl = setupCollection(false);
-runQueryWithCollation(noCollationColl, collation);
-
-// Tests to verify that the projection code inherits collection level collation in the absence of
-// query level collation.
-collWithCollation = setupCollection(collation);
-runQueryWithCollation(collWithCollation, null);
-
-// The output of this should not depend on the collection level collation and simple collation
-// should be applied always.
-function queryWithSimpleCollation(testColl) {
- const elemMatchOutput =
- testColl.find({str: 'A', elemMatch: {$elemMatch: {str: "a"}}}, {_id: 1, 'elemMatch.$': 1})
- .collation({locale: "simple"})
- .toArray();
- assert.sameMembers(elemMatchOutput, [{_id: 2, elemMatch: [{str: "a"}]}]);
-
- // Test findAndModify command with 'update'. Ensure that simple collation is always honored.
- const findAndUpdateOutput = testColl.findAndModify({
- query: {str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- update: {$set: {updated: true}},
- collation: {locale: "simple"}
- });
- assert.docEq(findAndUpdateOutput, {_id: 2, elemMatch: [{str: "a"}]});
-
- // Test findAndModify command with remove:true. Ensure that simple collation is always honored.
- const findAndRemoveOutput = testColl.findAndModify({
- query: {_id: 2, str: 'A', elemMatch: {$elemMatch: {str: "a"}}},
- fields: {_id: 1, 'elemMatch.$': 1, updated: 1},
- remove: true,
- collation: {locale: "simple"},
- });
- assert.docEq(findAndRemoveOutput, {_id: 2, elemMatch: [{str: "a"}], updated: true});
-}
-
-noCollationColl = setupCollection(false);
-queryWithSimpleCollation(noCollationColl);
-
-collWithCollation = setupCollection(collation);
-queryWithSimpleCollation(collWithCollation);
-
-// Test with views.
-(function viewWithCollation() {
- collWithCollation = setupCollection(collation);
- db[jsTestName() + "_view"].drop();
- assert.commandWorked(
- db.createView(jsTestName() + "_view", withCollationCollName, [], {collation: collation}));
- const viewColl = db[jsTestName() + "_view"];
-})();
-})();
diff --git a/jstests/libs/parallelTester.js b/jstests/libs/parallelTester.js
index 202f32ec74d..f67f6cb6685 100644
--- a/jstests/libs/parallelTester.js
+++ b/jstests/libs/parallelTester.js
@@ -260,7 +260,6 @@ if (typeof _threadInject != "undefined") {
"merge_sort_collation.js",
"explode_for_sort_fetch.js",
"or_to_in.js",
- "project_with_collation.js",
"update_pipeline_shell_helpers.js",
"update_with_pipeline.js",
"verify_update_mods.js",
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index ddedccd0fa0..dc702879df3 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -83,17 +83,11 @@ std::unique_ptr<FindCommandRequest> parseCmdObjectToFindCommandRequest(Operation
boost::intrusive_ptr<ExpressionContext> makeExpressionContext(
OperationContext* opCtx,
const FindCommandRequest& findCommand,
- const CollectionPtr& collPtr,
boost::optional<ExplainOptions::Verbosity> verbosity) {
std::unique_ptr<CollatorInterface> collator;
if (!findCommand.getCollation().isEmpty()) {
collator = uassertStatusOK(CollatorFactoryInterface::get(opCtx->getServiceContext())
->makeFromBSON(findCommand.getCollation()));
- } else if (collPtr && collPtr->getDefaultCollator()) {
- // The 'collPtr' will be null for views, but we don't need to worry about views here. The
- // views will get rewritten into aggregate command and will regenerate the
- // ExpressionContext.
- collator = collPtr->getDefaultCollator()->clone();
}
// Although both 'find' and 'aggregate' commands have an ExpressionContext, some of the data
@@ -262,11 +256,7 @@ public:
// Finish the parsing step by using the FindCommandRequest to create a CanonicalQuery.
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
-
- // The collection may be NULL. If so, getExecutor() should handle it by returning an
- // execution tree with an EOFStage.
- const auto& collection = ctx->getCollection();
- auto expCtx = makeExpressionContext(opCtx, *findCommand, collection, verbosity);
+ auto expCtx = makeExpressionContext(opCtx, *findCommand, verbosity);
const bool isExplain = true;
auto cq = uassertStatusOK(
CanonicalQuery::canonicalize(opCtx,
@@ -311,6 +301,10 @@ public:
return;
}
+ // The collection may be NULL. If so, getExecutor() should handle it by returning an
+ // execution tree with an EOFStage.
+ const auto& collection = ctx->getCollection();
+
// Get the execution plan for the query.
bool permitYield = true;
auto exec =
@@ -444,10 +438,7 @@ public:
// Finish the parsing step by using the FindCommandRequest to create a CanonicalQuery.
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
-
- const auto& collection = ctx->getCollection();
- auto expCtx =
- makeExpressionContext(opCtx, *findCommand, collection, boost::none /* verbosity */);
+ auto expCtx = makeExpressionContext(opCtx, *findCommand, boost::none /* verbosity */);
auto cq = uassertStatusOK(
CanonicalQuery::canonicalize(opCtx,
std::move(findCommand),
@@ -478,6 +469,8 @@ public:
return;
}
+ const auto& collection = ctx->getCollection();
+
if (cq->getFindCommandRequest().getReadOnce()) {
// The readOnce option causes any storage-layer cursors created during plan
// execution to assume read data will not be needed again and need not be cached.
diff --git a/src/mongo/db/ops/parsed_delete.cpp b/src/mongo/db/ops/parsed_delete.cpp
index 26006974eaa..6075a550e2f 100644
--- a/src/mongo/db/ops/parsed_delete.cpp
+++ b/src/mongo/db/ops/parsed_delete.cpp
@@ -146,12 +146,4 @@ std::unique_ptr<CanonicalQuery> ParsedDelete::releaseParsedQuery() {
return std::move(_canonicalQuery);
}
-void ParsedDelete::setCollator(std::unique_ptr<CollatorInterface> collator) {
- if (_canonicalQuery) {
- _canonicalQuery->setCollator(std::move(collator));
- } else {
- _expCtx->setCollator(std::move(collator));
- }
-}
-
} // namespace mongo
diff --git a/src/mongo/db/ops/parsed_delete.h b/src/mongo/db/ops/parsed_delete.h
index 6d6cb890681..ccf6b842884 100644
--- a/src/mongo/db/ops/parsed_delete.h
+++ b/src/mongo/db/ops/parsed_delete.h
@@ -115,8 +115,6 @@ public:
return _expCtx;
}
- void setCollator(std::unique_ptr<CollatorInterface> collator);
-
private:
// Transactional context. Not owned by us.
OperationContext* _opCtx;
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 2ae1cfd906f..28e3c96934b 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -1331,13 +1331,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele
expCtx->setIsCappedDelete();
}
- // If the parsed delete does not have a user-specified collation, set it from the collection
- // default.
- if (collection && parsedDelete->getRequest()->getCollation().isEmpty() &&
- collection->getDefaultCollator()) {
- parsedDelete->setCollator(collection->getDefaultCollator()->clone());
- }
-
if (collection && collection->isCapped()) {
// This check is duplicated from CollectionImpl::deleteDocument() for two reasons:
// - Performing a remove on an empty capped collection would not call