Skip to content

Commit bcde4c4

Browse files
committed
SERVER-42441 renameCollectionForApplyOps should always rename the target out of the way if it exists
1 parent 351205d commit bcde4c4

File tree

3 files changed

+35
-9
lines changed

3 files changed

+35
-9
lines changed

jstests/replsets/apply_ops_idempotency.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ var tests = {
144144
mydb.adminCommand({renameCollection: z.getFullName(), to: y.getFullName()}));
145145
return [mydb, otherdb];
146146
},
147+
renameCollectionAcrossDatabasesWithDropAndConvertToCapped: (db1) => {
148+
let db2 = db1.getSiblingDB(db1 + '_');
149+
assert.commandWorked(db1.createCollection("a"));
150+
assert.commandWorked(db1.createCollection("b"));
151+
assert.commandWorked(db2.createCollection("c"));
152+
assert.commandWorked(db2.createCollection("d"));
153+
let [a, b] = getCollections(db1, ['a', 'b']);
154+
let [c, d] = getCollections(db2, ['c', 'd']);
155+
156+
assert.commandWorked(db1.adminCommand(
157+
{renameCollection: a.getFullName(), to: c.getFullName(), dropTarget: true}));
158+
159+
assert(d.drop());
160+
161+
assert.commandWorked(db1.adminCommand(
162+
{renameCollection: c.getFullName(), to: d.getFullName(), dropTarget: false}));
163+
164+
assert.commandWorked(db1.adminCommand(
165+
{renameCollection: b.getFullName(), to: c.getFullName(), dropTarget: false}));
166+
assert.commandWorked(db2.runCommand({convertToCapped: "d", size: 1000}));
167+
168+
return [db1, db2];
169+
},
147170
createIndex: (mydb) => {
148171
let [x, y] = getCollections(mydb, ['x', 'y']);
149172
assert.commandWorked(x.createIndex({x: 1}));

src/mongo/db/catalog/rename_collection.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ bool isReplicatedChanged(OperationContext* opCtx,
8989
Status checkSourceAndTargetNamespaces(OperationContext* opCtx,
9090
const NamespaceString& source,
9191
const NamespaceString& target,
92-
RenameCollectionOptions options) {
92+
RenameCollectionOptions options,
93+
bool targetExistsAllowed) {
9394

9495
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
9596
if (opCtx->writesAreReplicated() && !replCoord->canAcceptWritesFor(opCtx, source))
@@ -129,7 +130,7 @@ Status checkSourceAndTargetNamespaces(OperationContext* opCtx,
129130
if (isCollectionSharded(opCtx, target))
130131
return {ErrorCodes::IllegalOperation, "cannot rename to a sharded collection"};
131132

132-
if (!options.dropTarget)
133+
if (!targetExistsAllowed && !options.dropTarget)
133134
return Status(ErrorCodes::NamespaceExists, "target namespace exists");
134135
}
135136

@@ -295,7 +296,8 @@ Status renameCollectionWithinDB(OperationContext* opCtx,
295296
sourceLock.emplace(opCtx, source, MODE_X);
296297
}
297298

298-
auto status = checkSourceAndTargetNamespaces(opCtx, source, target, options);
299+
auto status = checkSourceAndTargetNamespaces(
300+
opCtx, source, target, options, /* targetExistsAllowed */ false);
299301
if (!status.isOK())
300302
return status;
301303

@@ -334,7 +336,8 @@ Status renameCollectionWithinDBForApplyOps(OperationContext* opCtx,
334336
dss->checkDbVersion(opCtx, dssLock);
335337
}
336338

337-
auto status = checkSourceAndTargetNamespaces(opCtx, source, target, options);
339+
auto status = checkSourceAndTargetNamespaces(
340+
opCtx, source, target, options, /* targetExistsAllowed */ true);
338341
if (!status.isOK())
339342
return status;
340343

@@ -371,7 +374,7 @@ Status renameCollectionWithinDBForApplyOps(OperationContext* opCtx,
371374
return Status::OK();
372375
});
373376
}
374-
if (uuidToDrop && uuidToDrop != targetColl->uuid()) {
377+
if (!uuidToDrop || (uuidToDrop && uuidToDrop != targetColl->uuid())) {
375378
// We need to rename the targetColl to a temporary name.
376379
auto status = renameTargetCollectionToTmp(
377380
opCtx, source, sourceColl->uuid(), db, target, targetColl->uuid());

src/mongo/db/catalog/rename_collection_test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,10 @@ TEST_F(RenameCollectionTest,
765765
_opObserver->renameOpTime = {};
766766

767767
_createCollection(_opCtx.get(), _sourceNss);
768-
_createCollection(_opCtx.get(), _targetNss);
768+
auto dropTargetUUID = _createCollectionWithUUID(_opCtx.get(), _targetNss);
769769
auto dbName = _sourceNss.db().toString();
770770
auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns() << "dropTarget"
771-
<< true);
771+
<< dropTargetUUID);
772772

773773
repl::OpTime renameOpTime = {Timestamp(Seconds(200), 1U), 1LL};
774774
ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), dbName, boost::none, cmd, renameOpTime));
@@ -787,10 +787,10 @@ DEATH_TEST_F(RenameCollectionTest,
787787
ASSERT_FALSE(_opCtx->writesAreReplicated());
788788

789789
_createCollection(_opCtx.get(), _sourceNss);
790-
_createCollection(_opCtx.get(), _targetNss);
790+
auto dropTargetUUID = _createCollectionWithUUID(_opCtx.get(), _targetNss);
791791
auto dbName = _sourceNss.db().toString();
792792
auto cmd = BSON("renameCollection" << _sourceNss.ns() << "to" << _targetNss.ns() << "dropTarget"
793-
<< true);
793+
<< dropTargetUUID);
794794

795795
repl::OpTime renameOpTime = {Timestamp(Seconds(200), 1U), 1LL};
796796
ASSERT_OK(renameCollectionForApplyOps(_opCtx.get(), dbName, boost::none, cmd, renameOpTime));

0 commit comments

Comments
 (0)