Files
mongo/jstests/core/txns/statement_ids_accepted.js

261 lines
8.8 KiB
JavaScript

// Makes sure all commands which are supposed to take statement ids do. This should test all
// commands that are allowed in transactions.
// @tags: [uses_transactions, uses_prepare_transaction]
(function() {
"use strict";
const dbName = "test";
const collName = "statement_ids_accepted";
const testDB = db.getSiblingDB(dbName);
const testColl = testDB[collName];
testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
assert.commandWorked(
testDB.createCollection(testColl.getName(), {writeConcern: {w: "majority"}}));
const sessionOptions = {causalConsistency: false};
const session = db.getMongo().startSession(sessionOptions);
const sessionDb = session.getDatabase(dbName);
let txnNumber = 0;
jsTestLog("Check that abortTransaction accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
find: collName,
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// abortTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
abortTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(1),
autocommit: false
}));
jsTestLog("Check that aggregate accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
aggregate: collName,
cursor: {},
pipeline: [{$match: {}}],
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// The applyOps command is intentionally left out.
jsTestLog("Check that commitTransaction accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
find: collName,
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// commitTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
commitTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(1),
autocommit: false
}));
jsTestLog("Check that delete accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
delete: collName,
deletes: [{q: {}, limit: 1}],
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
jsTestLog("Check that distinct accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
distinct: collName,
key: "x",
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// The doTxn command is intentionally left out.
jsTestLog("Check that find and getmore accept a statement ID");
// Put in some data to find so getMore has a cursor to use.
assert.writeOK(testColl.insert([{_id: 0}, {_id: 1}], {writeConcern: {w: "majority"}}));
let res = assert.commandWorked(sessionDb.runCommand({
find: collName,
batchSize: 1,
filter: {},
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
assert.commandWorked(sessionDb.runCommand({
getMore: res.cursor.id,
collection: collName,
batchSize: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(1),
autocommit: false
}));
jsTestLog("Check that findandmodify accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
findandmodify: collName,
remove: true,
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
jsTestLog("Check that findAndModify accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
findAndModify: collName,
remove: true,
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// Abort the transaction to release locks.
// abortTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
abortTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
autocommit: false
}));
jsTestLog("Check that insert accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
insert: collName,
documents: [{_id: "doc1"}],
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// Abort the transaction to release locks.
// abortTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
abortTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(1),
autocommit: false
}));
const isMongos = assert.commandWorked(db.runCommand("ismaster")).msg === "isdbgrid";
if (!isMongos) {
// Skip commands that do not exist on mongos.
jsTestLog("Check that geoSearch accepts a statement ID");
assert.writeOK(testColl.insert({geo: {type: "Point", coordinates: [0, 0]}, a: 0}),
{writeConcern: {w: "majority"}});
assert.writeOK(testColl.insert({geoh: {lat: 0, long: 0}, b: 0}),
{writeConcern: {w: "majority"}});
assert.commandWorked(sessionDb.runCommand({
createIndexes: collName,
indexes: [
{name: "geo", key: {geo: "2dsphere"}},
{name: "geoh", key: {geoh: "geoHaystack", b: 1}, bucketSize: 1}
],
writeConcern: {w: "majority"}
}));
// Ensure the snapshot is available following the index creation.
assert.soonNoExcept(function() {
testColl.find({}, {readConcern: {level: "snapshot"}});
return true;
});
jsTestLog("Check that geoSearch accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
geoSearch: collName,
search: {b: 0},
near: [0, 0],
maxDistance: 1,
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
jsTestLog("Check that prepareTransaction accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
insert: collName,
documents: [{_id: "doc2"}],
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// prepareTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
prepareTransaction: 1,
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(1),
autocommit: false
}));
assert.commandWorked(sessionDb.adminCommand({
abortTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(2),
autocommit: false
}));
assert.commandFailedWithCode(sessionDb.runCommand({
prepareTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(0),
autocommit: false
}),
ErrorCodes.Unauthorized);
}
// refreshLogicalSessionCacheNow is intentionally omitted.
jsTestLog("Check that update accepts a statement ID");
assert.commandWorked(sessionDb.runCommand({
update: collName,
updates: [{q: {_id: "doc1"}, u: {$inc: {a: 1}}}],
readConcern: {level: "snapshot"},
txnNumber: NumberLong(txnNumber),
stmtId: NumberInt(0),
startTransaction: true,
autocommit: false
}));
// Abort the last transaction because it appears the system stalls during shutdown if
// a transaction is open.
// abortTransaction can only be run on the admin database.
assert.commandWorked(sessionDb.adminCommand({
abortTransaction: 1,
txnNumber: NumberLong(txnNumber++),
stmtId: NumberInt(1),
autocommit: false
}));
session.endSession();
}());