summaryrefslogtreecommitdiff
path: root/jstests/core/regex.js
blob: 1c6a9d6a3bbe785dcc2f9f11ba3985bfc6d90c30 (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
(function() {
    'use strict';

    const t = db.jstests_regex;

    const isMaster = db.runCommand("ismaster");
    assert.commandWorked(isMaster);
    const isMongos = (isMaster.msg === "isdbgrid");

    t.drop();
    assert.writeOK(t.save({a: "bcd"}));
    assert.eq(1, t.count({a: /b/}), "A");
    assert.eq(1, t.count({a: /bc/}), "B");
    assert.eq(1, t.count({a: /bcd/}), "C");
    assert.eq(0, t.count({a: /bcde/}), "D");

    t.drop();
    assert.writeOK(t.save({a: {b: "cde"}}));
    assert.eq(1, t.count({'a.b': /de/}), "E");

    t.drop();
    assert.writeOK(t.save({a: {b: ["cde"]}}));
    assert.eq(1, t.count({'a.b': /de/}), "F");

    t.drop();
    assert.writeOK(t.save({a: [{b: "cde"}]}));
    assert.eq(1, t.count({'a.b': /de/}), "G");

    t.drop();
    assert.writeOK(t.save({a: [{b: ["cde"]}]}));
    assert.eq(1, t.count({'a.b': /de/}), "H");

    //
    // Confirm match and explain serialization for $elemMatch with $regex.
    //
    t.drop();
    assert.writeOK(t.insert({x: ["abc"]}));

    const query = {x: {$elemMatch: {$regex: 'ABC', $options: 'i'}}};
    assert.eq(1, t.count(query));

    const result = t.find(query).explain();
    assert.commandWorked(result);

    if (!isMongos) {
        assert(result.hasOwnProperty("queryPlanner"));
        assert(result.queryPlanner.hasOwnProperty("parsedQuery"), tojson(result));
        assert.eq(result.queryPlanner.parsedQuery, query);
    }

    //
    // Disallow embedded null bytes when using $regex syntax.
    //
    t.drop();
    assert.throws(function() {
        t.find({a: {$regex: "a\0b", $options: "i"}}).itcount();
    });
    assert.throws(function() {
        t.find({a: {$regex: "ab", $options: "i\0"}}).itcount();
    });
    assert.throws(function() {
        t.find({key: {$regex: 'abcd\0xyz'}}).explain();
    });

    //
    // Confirm $options and mode specified in $regex are not allowed to be specified together.
    //
    t.drop();
    assert.commandWorked(t.insert({x: ["abc"]}));

    let regexFirst = assert.throws(() => t.find({x: {$regex: /ab/i, $options: 's'}}).itcount());
    assert.commandFailedWithCode(regexFirst, 51075);

    let optsFirst = assert.throws(() => t.find({x: {$options: 's', $regex: /ab/i}}).itcount());
    assert.commandFailedWithCode(optsFirst, 51074);

    t.drop();
    assert.commandWorked(t.save({x: ["abc"]}));

    assert.eq(1, t.count({x: {$regex: /ABC/i}}));
    assert.eq(1, t.count({x: {$regex: /ABC/, $options: 'i'}}));
    assert.eq(1, t.count({x: {$options: 'i', $regex: /ABC/}}));
})();