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
|
/**
* Tests that the CannotConvertIndexToUnique error returned when collmod fails to convert an index
* to unique contains correct information about violations found.
*
* @tags: [
* # Cannot implicitly shard accessed collections because of collection existing when none
* # expected.
* assumes_no_implicit_collection_creation_after_drop, # common tag in collMod tests.
* requires_fcv_52,
* requires_non_retryable_commands, # common tag in collMod tests.
* # TODO(SERVER-61181): Fix validation errors under ephemeralForTest.
* incompatible_with_eft,
* # TODO(SERVER-61182): Fix WiredTigerKVEngine::alterIdentMetadata() under inMemory.
* requires_persistence,
* ]
*/
(function() {
'use strict';
load("jstests/libs/fixture_helpers.js"); // For 'isMongos'
const collModIndexUniqueEnabled = assert
.commandWorked(db.getMongo().adminCommand(
{getParameter: 1, featureFlagCollModIndexUnique: 1}))
.featureFlagCollModIndexUnique.value;
if (!collModIndexUniqueEnabled) {
jsTestLog('Skipping test because the collMod unique index feature flag is disabled.');
return;
}
function sortViolationsArray(arr) {
// Sorting unsorted arrays of unsorted arrays -- Sort subarrays, then sort main array by first
// key of subarray.
for (let i = 0; i < arr.length; i++) {
arr[i].ids = arr[i].ids.sort();
}
return arr.sort(function(a, b) {
if (a.ids[0] < b.ids[0]) {
return -1;
}
if (a.ids[0] > b.ids[0]) {
return 1;
}
return 0;
});
}
const collName = 'collmod_convert_to_unique_violations';
const coll = db.getCollection(collName);
coll.drop();
// Checks that the violations match what we expect.
function assertFailedWithViolations(keyPattern, violations) {
// First sets 'prepareUnique' before converting the index to unique.
assert.commandWorked(
db.runCommand({collMod: collName, index: {keyPattern: keyPattern, prepareUnique: true}}));
const result =
db.runCommand({collMod: collName, index: {keyPattern: keyPattern, unique: true}});
assert.commandFailedWithCode(result, ErrorCodes.CannotConvertIndexToUnique);
assert.eq(
bsonWoCompare(sortViolationsArray(result.violations), sortViolationsArray(violations)),
0,
tojson(result));
// Resets 'prepareUnique'.
assert.commandWorked(
db.runCommand({collMod: collName, index: {keyPattern: keyPattern, prepareUnique: false}}));
}
assert.commandWorked(db.createCollection(collName));
// Create regular indexes and try to use collMod to convert them to unique indexes.
assert.commandWorked(coll.createIndex({a: 1}));
assert.commandWorked(coll.createIndex({a: 1, b: 1}));
// Conversion should fail when there are existing duplicates, reporting correct number of
// violations.
assert.commandWorked(coll.insert({_id: 1, a: 100, b: 1}));
assert.commandWorked(coll.insert({_id: 2, a: 100, b: 2}));
assertFailedWithViolations({a: 1}, [{ids: [1, 2]}]);
assert.commandWorked(coll.insert({_id: 3, a: 100, b: 3}));
assertFailedWithViolations({a: 1}, [{ids: [1, 2, 3]}]);
assert.commandWorked(coll.insert({_id: 4, a: 101, b: 4}));
assertFailedWithViolations({a: 1}, [{ids: [1, 2, 3]}]);
assert.commandWorked(coll.insert({_id: 5, a: 105, b: 5}));
assert.commandWorked(coll.insert({_id: 6, a: 105, b: 6}));
assertFailedWithViolations({a: 1}, [{ids: [1, 2, 3]}, {ids: [5, 6]}]);
// Test that compound indexes work as expected.
assert.commandWorked(coll.insert({_id: 7, a: 105, b: 6}));
assertFailedWithViolations({a: 1, b: 1}, [{ids: [6, 7]}]);
assert.commandWorked(coll.insert({_id: 8, a: 105, b: 6}));
assertFailedWithViolations({a: 1, b: 1}, [{ids: [6, 7, 8]}]);
assert.commandWorked(coll.insert({_id: 9, a: 101, b: 4}));
assertFailedWithViolations({a: 1, b: 1}, [{ids: [4, 9]}, {ids: [6, 7, 8]}]);
assert.commandWorked(coll.insert({_id: "10", a: 101, b: 4}));
assertFailedWithViolations({a: 1, b: 1}, [{ids: [4, 9, "10"]}, {ids: [6, 7, 8]}]);
})();
|