summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/crud_timestamps.js
blob: 07718be5bbc37965e6dac90e596c8138d0031f71 (plain)
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
// @tags: [requires_replication, uses_transactions, uses_atclustertime]

// Test the correct timestamping of insert, update, and delete writes along with their accompanying
// index updates.
//

(function() {
"use strict";

const dbName = "test";
const collName = "coll";

const rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
const testDB = rst.getPrimary().getDB(dbName);
const coll = testDB.getCollection(collName);

if (!testDB.serverStatus().storageEngine.supportsSnapshotReadConcern) {
    rst.stopSet();
    return;
}

// Turn off timestamp reaping.
assert.commandWorked(testDB.adminCommand({
    configureFailPoint: "WTPreserveSnapshotHistoryIndefinitely",
    mode: "alwaysOn",
}));

const session = testDB.getMongo().startSession({causalConsistency: false});
const sessionDb = session.getDatabase(dbName);
const response = assert.commandWorked(testDB.createCollection("coll"));
const startTime = response.operationTime;

function check(atClusterTime, expected) {
    session.startTransaction({readConcern: {level: "snapshot", atClusterTime: atClusterTime}});
    // Check both a collection scan and scanning the _id index.
    [{$natural: 1}, {_id: 1}].forEach(sort => {
        let response = assert.commandWorked(
            sessionDb.runCommand({find: collName, sort: sort, singleBatch: true}));
        assert.eq(expected, response.cursor.firstBatch);
    });
    assert.commandWorked(session.commitTransaction_forTesting());
}

// insert

let request = {insert: coll.getName(), documents: [{_id: 1}, {_id: 2}], ordered: false};
assert.commandWorked(coll.runCommand(request));

const oplog = rst.getPrimary().getDB("local").getCollection("oplog.rs");
let ts1 = oplog.findOne({o: {_id: 1}}).ts;
let ts2 = oplog.findOne({o: {_id: 2}}).ts;

check(startTime, []);
check(ts1, [{_id: 1}]);
check(ts2, [{_id: 1}, {_id: 2}]);

// upsert

request = {
    update: coll.getName(),
    updates: [
        {q: {_id: 3, a: 1}, u: {$set: {a: 2}}, upsert: true},
        {q: {_id: 4, a: 1}, u: {$set: {a: 3}}, upsert: true}
    ],
    ordered: true
};
assert.commandWorked(coll.runCommand(request));

ts1 = oplog.findOne({o: {_id: 3, a: 2}}).ts;
ts2 = oplog.findOne({o: {_id: 4, a: 3}}).ts;

check(ts1, [{_id: 1}, {_id: 2}, {_id: 3, a: 2}]);
check(ts2, [{_id: 1}, {_id: 2}, {_id: 3, a: 2}, {_id: 4, a: 3}]);

// update

request = {
    update: coll.getName(),
    updates: [{q: {_id: 3, a: 2}, u: {$set: {a: 4}}}, {q: {_id: 4, a: 3}, u: {$set: {a: 5}}}],
    ordered: true
};
assert.commandWorked(coll.runCommand(request));

ts1 = oplog.findOne({op: 'u', o2: {_id: 3}}).ts;
ts2 = oplog.findOne({op: 'u', o2: {_id: 4}}).ts;

check(ts1, [{_id: 1}, {_id: 2}, {_id: 3, a: 4}, {_id: 4, a: 3}]);
check(ts2, [{_id: 1}, {_id: 2}, {_id: 3, a: 4}, {_id: 4, a: 5}]);

// delete

request = {
    delete: coll.getName(),
    deletes: [{q: {}, limit: 0}],
    ordered: false
};

assert.commandWorked(coll.runCommand(request));

ts1 = oplog.findOne({op: 'd', o: {_id: 1}}).ts;
ts2 = oplog.findOne({op: 'd', o: {_id: 2}}).ts;
let ts3 = oplog.findOne({op: 'd', o: {_id: 3}}).ts;
let ts4 = oplog.findOne({op: 'd', o: {_id: 4}}).ts;

check(ts1, [{_id: 2}, {_id: 3, a: 4}, {_id: 4, a: 5}]);
check(ts2, [{_id: 3, a: 4}, {_id: 4, a: 5}]);
check(ts3, [{_id: 4, a: 5}]);
check(ts4, []);

session.endSession();
rst.stopSet();
}());