mirror of https://github.com/mongodb/mongo
161 lines
6.7 KiB
JavaScript
161 lines
6.7 KiB
JavaScript
/**
|
|
* Tests how replication handles inserts and updates with "Timestamp(0,0)" values.
|
|
*
|
|
* @tags: [
|
|
* multiversion_incompatible,
|
|
* ]
|
|
*/
|
|
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
|
|
const dbName = "test";
|
|
const collName = "empty_ts_repl";
|
|
|
|
const rst = new ReplSetTest({
|
|
name: jsTestName(),
|
|
nodes: 2,
|
|
});
|
|
rst.startSet();
|
|
rst.initiate();
|
|
|
|
const primaryColl = rst.getPrimary().getDB(dbName).getCollection(collName);
|
|
const secondaryColl = rst.getSecondary().getDB(dbName).getCollection(collName);
|
|
const emptyTs = Timestamp(0, 0);
|
|
|
|
// Insert several documents. For the first document inserted (_id=101), the empty timestamp value
|
|
// in field "a" should get replaced with the current timestamp.
|
|
assert.commandWorked(primaryColl.insert({_id: 101, a: emptyTs}));
|
|
assert.commandWorked(primaryColl.insert({_id: 102, a: 1}));
|
|
assert.commandWorked(primaryColl.insert({_id: 103, a: 2}));
|
|
assert.commandWorked(primaryColl.insert({_id: 106, a: 3}));
|
|
assert.commandWorked(primaryColl.insert({_id: 107, a: 4}));
|
|
assert.commandWorked(primaryColl.insert({_id: 108, a: 5}));
|
|
assert.commandWorked(primaryColl.insert({_id: 109, a: 6}));
|
|
assert.commandWorked(primaryColl.insert({_id: 110, a: 7}));
|
|
assert.commandWorked(primaryColl.insert({_id: 111, a: 8}));
|
|
|
|
// Wait for all the inserted documents to replicate to the secondaries.
|
|
rst.awaitReplication();
|
|
|
|
// Use a replacement-style update to update _id=102. This should result in field "a" being set to
|
|
// the current timestamp.
|
|
assert.commandWorked(primaryColl.update({_id: 102}, {a: emptyTs}));
|
|
|
|
// Use a replacement-style findAndModify to update _id=103. This should result in field "a" being
|
|
// set to the current timestamp.
|
|
let findAndModifyResult = primaryColl.findAndModify({query: {_id: 103}, update: {a: emptyTs}});
|
|
assert.eq(findAndModifyResult, {_id: 103, a: 2});
|
|
|
|
// Do a replacement-style update to add a new document with _id=104. This should result in field "a"
|
|
// being set to the current timestamp.
|
|
assert.commandWorked(primaryColl.update({_id: 104}, {a: emptyTs}, {upsert: true}));
|
|
|
|
// Do a replacement-style findAndModify to add a new document with _id=105. This should result in
|
|
// field "a" being set to the current timestamp.
|
|
findAndModifyResult = primaryColl.findAndModify({query: {_id: 105}, update: {a: emptyTs}, upsert: true});
|
|
assert.eq(findAndModifyResult, null);
|
|
|
|
// For the rest of the commands below, the empty timestamp values stored in field "a" should be
|
|
// preserved as-is.
|
|
|
|
// Do an update-operator-style update to update _id=106.
|
|
assert.commandWorked(primaryColl.update({_id: 106}, {$set: {a: emptyTs}}));
|
|
|
|
// Do an update-operator-style findAndModify to update _id=107.
|
|
findAndModifyResult = primaryColl.findAndModify({query: {_id: 107}, update: {$set: {a: emptyTs}}});
|
|
assert.eq(findAndModifyResult, {_id: 107, a: 4});
|
|
|
|
// Do a pipeline-style update to update _id=108.
|
|
assert.commandWorked(primaryColl.update({_id: 108}, [{$addFields: {a: emptyTs}}]));
|
|
|
|
// Do a pipeline-style findAndModify to update _id=109.
|
|
findAndModifyResult = primaryColl.findAndModify({query: {_id: 109}, update: [{$addFields: {a: emptyTs}}]});
|
|
assert.eq(findAndModifyResult, {_id: 109, a: 6});
|
|
|
|
// Do a pipeline-style update with $internalApplyOplogUpdate to update _id=110.
|
|
assert.commandWorked(
|
|
primaryColl.update({_id: 110}, [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}]),
|
|
);
|
|
|
|
// Do a pipeline-style findAndModify with $internalApplyOplogUpdate to update _id=111.
|
|
findAndModifyResult = primaryColl.findAndModify({
|
|
query: {_id: 111},
|
|
update: [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
|
|
});
|
|
assert.eq(findAndModifyResult, {_id: 111, a: 8});
|
|
|
|
// Do an update-operator-style update to add a new document with _id=112.
|
|
assert.commandWorked(primaryColl.update({_id: 112}, {$set: {a: emptyTs}}, {upsert: true}));
|
|
|
|
// Do an update-operator-style findAndModify to add a new document with _id=113.
|
|
findAndModifyResult = primaryColl.findAndModify({query: {_id: 113}, update: {$set: {a: emptyTs}}, upsert: true});
|
|
assert.eq(findAndModifyResult, null);
|
|
|
|
// Do a pipeline-style update to add a new document with _id=114.
|
|
assert.commandWorked(primaryColl.update({_id: 114}, [{$addFields: {a: emptyTs}}], {upsert: true}));
|
|
|
|
// Do a pipeline-style findAndModify to add a new document with _id=115.
|
|
findAndModifyResult = primaryColl.findAndModify({
|
|
query: {_id: 115},
|
|
update: [{$addFields: {a: emptyTs}}],
|
|
upsert: true,
|
|
});
|
|
assert.eq(findAndModifyResult, null);
|
|
|
|
// Do a pipeline-style update with $internalApplyOplogUpdate to add a new document _id=116.
|
|
assert.commandWorked(
|
|
primaryColl.update({_id: 116}, [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}], {
|
|
upsert: true,
|
|
}),
|
|
);
|
|
|
|
// Do a pipeline-style findAndModify with $internalApplyOplogUpdate to add a new document _id=117.
|
|
findAndModifyResult = primaryColl.findAndModify({
|
|
query: {_id: 117},
|
|
update: [{$_internalApplyOplogUpdate: {oplogUpdate: {$v: 2, diff: {i: {a: emptyTs}}}}}],
|
|
upsert: true,
|
|
});
|
|
assert.eq(findAndModifyResult, null);
|
|
|
|
rst.awaitReplication();
|
|
|
|
// Verify that all the insert, update, and findAndModify commands behaved the way we expect and that
|
|
// they all were replicated correctly to the secondaries.
|
|
for (let i = 101; i <= 117; ++i) {
|
|
let result = primaryColl.findOne({_id: i});
|
|
let secondaryResult = secondaryColl.findOne({_id: i});
|
|
|
|
assert.eq(tojson(result), tojson(secondaryResult), "_id=" + i);
|
|
|
|
if (i >= 106) {
|
|
assert.eq(tojson(result.a), tojson(emptyTs), "_id=" + i);
|
|
} else {
|
|
assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + i);
|
|
}
|
|
}
|
|
|
|
// Insert a document with _id=Timestamp(0,0).
|
|
assert.commandWorked(primaryColl.insert({_id: emptyTs, a: 9}));
|
|
|
|
// Verify the document we just inserted can be retrieved using the filter "{_id: Timestamp(0,0)}".
|
|
let result = primaryColl.findOne({_id: emptyTs});
|
|
assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
|
|
assert.eq(tojson(result.a), tojson(9), "_id=" + tojson(emptyTs));
|
|
|
|
// Do a replacement-style update on the document.
|
|
assert.commandWorked(primaryColl.update({_id: emptyTs}, {_id: emptyTs, a: emptyTs}));
|
|
|
|
// Verify the document we just updated can still be retrieved using "{_id: Timestamp(0,0)}" and
|
|
// verify that field "a" was set to the current timestamp.
|
|
result = primaryColl.findOne({_id: emptyTs});
|
|
assert.eq(tojson(result._id), tojson(emptyTs), "_id=" + tojson(emptyTs));
|
|
assert.neq(tojson(result.a), tojson(emptyTs), "_id=" + tojson(emptyTs));
|
|
|
|
rst.awaitReplication();
|
|
|
|
// Verify that the document was replicated correctly to the secondaries.
|
|
let secondaryResult = secondaryColl.findOne({_id: emptyTs});
|
|
assert.eq(tojson(result), tojson(secondaryResult), "_id=" + tojson(emptyTs));
|
|
|
|
rst.stopSet();
|