1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/**
* Tests that $lookup respects the user-specified collation or the inherited local collation
* when performing comparisons on a foreign collection with a different default collation. Exercises
* the fix for SERVER-43350.
*/
load("jstests/aggregation/extras/utils.js"); // For anyEq.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
(function() {
"use strict";
load("jstests/libs/fixture_helpers.js"); // For isSharded.
const testDB = db.getSiblingDB(jsTestName());
assert.commandWorked(testDB.dropDatabase());
// TODO SERVER-64482 Reenable this test when SERVER-64482 is done.
if (checkSBEEnabled(testDB, ["featureFlagSBELookupPushdown"])) {
jsTestLog("Skipping test because SBE and SBE $lookup features are both enabled.");
return;
}
const caseInsensitiveCollation = {
locale: "en_US",
strength: 1
};
const simpleCollation = {
locale: "simple"
};
assert.commandWorked(testDB.createCollection("no_collation"));
assert.commandWorked(
testDB.createCollection("case_insensitive", {collation: caseInsensitiveCollation}));
const noCollationColl = testDB.no_collation;
const caseInsensitiveColl = testDB.case_insensitive;
// Do not run the rest of the tests if the foreign collection is implicitly sharded but the flag to
// allow $lookup/$graphLookup into a sharded collection is disabled.
const getShardedLookupParam = db.adminCommand({getParameter: 1, featureFlagShardedLookup: 1});
const isShardedLookupEnabled = getShardedLookupParam.hasOwnProperty("featureFlagShardedLookup") &&
getShardedLookupParam.featureFlagShardedLookup.value;
if (FixtureHelpers.isSharded(caseInsensitiveColl) && !isShardedLookupEnabled) {
return;
}
assert.commandWorked(
noCollationColl.insert([{_id: "a"}, {_id: "b"}, {_id: "c"}, {_id: "d"}, {_id: "e"}]));
assert.commandWorked(
caseInsensitiveColl.insert([{_id: "a"}, {_id: "B"}, {_id: "c"}, {_id: "D"}, {_id: "e"}]));
const lookupWithPipeline = (foreignColl) => {
return {
$lookup: {from: foreignColl.getName(), as: "foreignMatch", let: {l_id: "$_id"}, pipeline: [{$match: {$expr: {$eq: ["$_id", "$$l_id"]}}}]}
};
};
const lookupNoPipeline = (foreignColl) => {
return {
$lookup: {from: foreignColl.getName(), localField: "_id", foreignField: "_id", as: "foreignMatch"}
};
};
for (let lookupInto of [lookupWithPipeline, lookupNoPipeline]) {
// Verify that a $lookup whose local collection has no default collation uses the simple
// collation for comparisons on a foreign collection with a non-simple default collation.
let results = noCollationColl.aggregate([lookupInto(caseInsensitiveColl)]).toArray();
assert(anyEq(results, [
{_id: "a", foreignMatch: [{_id: "a"}]},
{_id: "b", foreignMatch: []},
{_id: "c", foreignMatch: [{_id: "c"}]},
{_id: "d", foreignMatch: []},
{_id: "e", foreignMatch: [{_id: "e"}]}
]));
// Verify that a $lookup whose local collection has no default collation but which is running in
// a pipeline with a non-simple user-specified collation uses the latter for comparisons on the
// foreign collection.
results =
noCollationColl
.aggregate([lookupInto(caseInsensitiveColl)], {collation: caseInsensitiveCollation})
.toArray();
assert(anyEq(results, [
{_id: "a", foreignMatch: [{_id: "a"}]},
{_id: "b", foreignMatch: [{_id: "B"}]},
{_id: "c", foreignMatch: [{_id: "c"}]},
{_id: "d", foreignMatch: [{_id: "D"}]},
{_id: "e", foreignMatch: [{_id: "e"}]}
]));
// Verify that a $lookup whose local collection has a non-simple collation uses the latter for
// comparisons on a foreign collection with no default collation.
results = caseInsensitiveColl.aggregate([lookupInto(noCollationColl)]).toArray();
assert(anyEq(results, [
{_id: "a", foreignMatch: [{_id: "a"}]},
{_id: "B", foreignMatch: [{_id: "b"}]},
{_id: "c", foreignMatch: [{_id: "c"}]},
{_id: "D", foreignMatch: [{_id: "d"}]},
{_id: "e", foreignMatch: [{_id: "e"}]}
]));
// Verify that a $lookup whose local collection has a non-simple collation but which is running
// in a pipeline with a user-specified simple collation uses the latter for comparisons on the
// foreign collection.
results =
caseInsensitiveColl.aggregate([lookupInto(noCollationColl)], {collation: simpleCollation})
.toArray();
assert(anyEq(results, [
{_id: "a", foreignMatch: [{_id: "a"}]},
{_id: "B", foreignMatch: []},
{_id: "c", foreignMatch: [{_id: "c"}]},
{_id: "D", foreignMatch: []},
{_id: "e", foreignMatch: [{_id: "e"}]}
]));
}
})();
|