summaryrefslogtreecommitdiff
path: root/jstests/aggregation/view_resolution_namespace_collision.js
blob: 497ac7d0a6eb0ffd7465828849e134e15585a627 (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
/**
 * Tests that view resolution works correctly when a cross-database aggregation targets a
 * collection and a view with the same name on different databases.
 *
 * @tags: [assumes_no_implicit_collection_creation_after_drop]
 */
(function() {
"use strict";

const testDBName = jsTestName();
const testDB = db.getSiblingDB(testDBName);
const siblingDBName = jsTestName() + "_otherDB";
const siblingDB = testDB.getSiblingDB(siblingDBName);

// Since cross-db $out only works against existing databases in a sharded environment, we create a
// dummy collection on 'siblingDB' to allow this test to run in a sharded environment.
assert.commandWorked(siblingDB.foo.insert({}));

const sourceCollName = "source";
const otherCollName = "other_coll";
const collidingCollName = "collision_collection";
const sourceColl = testDB[sourceCollName];
const otherColl = testDB[otherCollName];

sourceColl.drop();
otherColl.drop();
testDB[collidingCollName].drop();

assert.commandWorked(sourceColl.insert({_id: 0}));
assert.commandWorked(otherColl.insert({_id: 0, notsecret: 1, secret: "really secret"}));

// Create a view on 'testDB' that will have the same name as the collection that $merge/$out
// will create.
assert.commandWorked(testDB.runCommand(
    {create: collidingCollName, viewOn: otherCollName, pipeline: [{$project: {secret: 0}}]}));

// Verify that the view gets resolved correctly when performing a cross database aggregation where
// the $lookup references a view on the source database and the $merge/$out references a collection
// on the target database with the same name as the view.
const lookupStage = {
    $lookup: {from: collidingCollName, localField: "_id", foreignField: "_id", as: "matches"}
};
const withoutWrite = sourceColl.aggregate([lookupStage]).toArray();
const mergeStage = {
    $merge: {into: {db: siblingDBName, coll: collidingCollName}}
};
const outStage = {
    $out: {db: siblingDBName, coll: collidingCollName}
};

// The aggregate should always use the view on 'testDB', not an empty collection on 'siblingDB'.
for (const writeStage of [mergeStage, outStage]) {
    sourceColl.aggregate([lookupStage, writeStage]).toArray();
    const withWrite = siblingDB[collidingCollName].find().toArray();
    assert.eq(withoutWrite, withWrite);
    siblingDB[collidingCollName].drop();
}

siblingDB.dropDatabase();
})();