summaryrefslogtreecommitdiff
path: root/jstests/core/views/views_creation.js
blob: 031dd6c563c34351d234ccaa2bb2f750a4b9bbd6 (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
// Test the creation of views with various options.
// @tags: [
//   assumes_superuser_permissions,
// ]

(function() {
    "use strict";

    // For arrayEq.
    load("jstests/aggregation/extras/utils.js");

    let viewsDB = db.getSiblingDB("views_creation");
    assert.commandWorked(viewsDB.dropDatabase());

    let collNames = viewsDB.getCollectionNames();
    assert.eq(0, collNames.length, tojson(collNames));

    // You cannot create a view that starts with 'system.'.
    assert.commandFailedWithCode(viewsDB.runCommand({create: "system.views", viewOn: "collection"}),
                                 ErrorCodes.InvalidNamespace,
                                 "Created an illegal view named 'system.views'");

    // We don't run this check on MMAPv1 as it automatically creates a system.indexes collection
    // when creating a database, which causes this command to fail with NamespaceAlreadyExists.
    if (jsTest.options().storageEngine !== "mmapv1") {
        assert.commandFailedWithCode(
            viewsDB.runCommand({create: "system.indexes", viewOn: "collection"}),
            ErrorCodes.InvalidNamespace,
            "Created an illegal view named 'system.indexes'");
    }

    // Collections that start with 'system.' that are not special to MongoDB fail with a different
    // error code.
    assert.commandFailedWithCode(viewsDB.runCommand({create: "system.foo", viewOn: "collection"}),
                                 ErrorCodes.InvalidNamespace,
                                 "Created an illegal view named 'system.foo'");

    // Create a collection for test purposes.
    assert.commandWorked(viewsDB.runCommand({create: "collection"}));

    let pipe = [{$match: {}}];

    // Create a "regular" view on a collection.
    assert.commandWorked(
        viewsDB.runCommand({create: "view", viewOn: "collection", pipeline: pipe}));

    collNames = viewsDB.getCollectionNames().filter((function(coll) {
        return !coll.startsWith("system.");
    }));
    assert.eq(2, collNames.length, collNames);
    let res = viewsDB.runCommand({listCollections: 1, filter: {type: "view"}});
    assert.commandWorked(res);

    // Ensure that the output of listCollections has all the expected options for a view.
    let expectedListCollectionsOutput = [{
        name: "view",
        type: "view",
        options: {viewOn: "collection", pipeline: pipe},
        info: {readOnly: true}
    }];
    assert(arrayEq(res.cursor.firstBatch, expectedListCollectionsOutput), tojson({
               expectedListCollectionsOutput: expectedListCollectionsOutput,
               got: res.cursor.firstBatch
           }));

    // Create a view on a non-existent collection.
    assert.commandWorked(
        viewsDB.runCommand({create: "viewOnNonexistent", viewOn: "nonexistent", pipeline: pipe}));

    // Create a view but don't specify a pipeline; this should default to something sane.
    assert.commandWorked(
        viewsDB.runCommand({create: "viewWithDefaultPipeline", viewOn: "collection"}));

    // Specifying a pipeline but no view namespace must fail.
    assert.commandFailed(viewsDB.runCommand({create: "viewNoViewNamespace", pipeline: pipe}));

    // Create a view on another view.
    assert.commandWorked(
        viewsDB.runCommand({create: "viewOnView", viewOn: "view", pipeline: pipe}));

    // View names are constrained to the same limitations as collection names.
    assert.commandFailed(viewsDB.runCommand({create: "", viewOn: "collection", pipeline: pipe}));
    assert.commandFailedWithCode(
        viewsDB.runCommand({create: "system.local.new", viewOn: "collection", pipeline: pipe}),
        ErrorCodes.InvalidNamespace);
    assert.commandFailedWithCode(
        viewsDB.runCommand({create: "dollar$", viewOn: "collection", pipeline: pipe}),
        ErrorCodes.InvalidNamespace);
}());