summaryrefslogtreecommitdiff
path: root/jstests/core/txns/no_implicit_collection_creation_in_txn.js
blob: 42494d50958265fab0e03fa4ba0333b1341566a2 (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
// Tests that it is illegal to implicitly create a collection using insert or upsert in a
// multi-document transaction.
// @tags: [uses_transactions]
(function() {
"use strict";

const dbName = "test";
const collName = "no_implicit_collection_creation_in_txn";
const testDB = db.getSiblingDB(dbName);
const testColl = testDB[collName];

testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});

const sessionOptions = {
    causalConsistency: false
};
const session = db.getMongo().startSession(sessionOptions);
const sessionDb = session.getDatabase(dbName);
const sessionColl = sessionDb[collName];

jsTest.log("Cannot implicitly create a collection in a transaction using insert.");

// Insert succeeds when the collection exists.
assert.commandWorked(testDB.createCollection(testColl.getName(), {writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
sessionColl.insert({_id: "doc"});
assert.commandWorked(session.commitTransaction_forTesting());
assert.eq({_id: "doc"}, testColl.findOne({_id: "doc"}));

// Insert fails when the collection does not exist.
assert.commandWorked(testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
assert.commandFailedWithCode(sessionColl.insert({_id: "doc"}),
                             ErrorCodes.OperationNotSupportedInTransaction);

// Committing the transaction should fail, since it should never have been started.
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
assert.eq(null, testColl.findOne({_id: "doc"}));

jsTest.log("Cannot implicitly create a collection in a transaction using update.");

// Update with upsert=true succeeds when the collection exists.
assert.commandWorked(testDB.createCollection(testColl.getName(), {writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
sessionColl.update({_id: "doc"}, {$set: {updated: true}}, {upsert: true});
assert.commandWorked(session.commitTransaction_forTesting());
assert.eq({_id: "doc", updated: true}, testColl.findOne({_id: "doc"}));

// Update with upsert=true fails when the collection does not exist.
assert.commandWorked(testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
assert.commandFailedWithCode(
    sessionColl.update({_id: "doc"}, {$set: {updated: true}}, {upsert: true}),
    ErrorCodes.OperationNotSupportedInTransaction);

// Committing the transaction should fail, since it should never have been started.
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
assert.eq(null, testColl.findOne({_id: "doc"}));

// Update with upsert=false succeeds when the collection does not exist.
session.startTransaction({writeConcern: {w: "majority"}});
assert.commandWorked(sessionColl.update({_id: "doc"}, {$set: {updated: true}}, {upsert: false}));
assert.commandWorked(session.commitTransaction_forTesting());
assert.eq(null, testColl.findOne({_id: "doc"}));

jsTest.log("Cannot implicitly create a collection in a transaction using findAndModify.");

// findAndModify with upsert=true succeeds when the collection exists.
assert.commandWorked(testDB.createCollection(testColl.getName(), {writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
let res =
    sessionColl.findAndModify({query: {_id: "doc"}, update: {$set: {updated: true}}, upsert: true});
assert.eq(null, res);
assert.commandWorked(session.commitTransaction_forTesting());
assert.eq({_id: "doc", updated: true}, testColl.findOne({_id: "doc"}));

// findAndModify with upsert=true fails when the collection does not exist.
assert.commandWorked(testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}));

session.startTransaction({writeConcern: {w: "majority"}});
res = assert.throws(() => sessionColl.findAndModify(
                        {query: {_id: "doc"}, update: {$set: {updated: true}}, upsert: true}));
assert.commandFailedWithCode(res, ErrorCodes.OperationNotSupportedInTransaction);

// Committing the transaction should fail, since it should never have been started.
assert.commandFailedWithCode(session.commitTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
assert.eq(null, testColl.findOne({_id: "doc"}));

// findAndModify with upsert=false succeeds when the collection does not exist.
session.startTransaction({writeConcern: {w: "majority"}});
res = sessionColl.findAndModify(
    {query: {_id: "doc"}, update: {$set: {updated: true}}, upsert: false});
assert.eq(null, res);
assert.commandWorked(session.commitTransaction_forTesting());
assert.eq(null, testColl.findOne({_id: "doc"}));

session.endSession();
}());