summaryrefslogtreecommitdiff
path: root/jstests/aggregation/bugs/server9840.js
blob: b3a73cfc3d7d05d42e9044f29b1eee4fadb52906 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// SERVER-9840 variables in expressions and $let

load('jstests/aggregation/extras/utils.js');
var t = db.server9840;
t.drop();

function test(expression, expected) {
    t.drop();
    t.insert({zero: 0, one: 1, two: 2, three: 3, nested: {four: 4}});

    // Test in projection:
    var result = t.aggregate({$project: {_id: 0, res: expression}}).toArray();
    assert.eq(result, [{res: expected}]);

    // Test in group:
    var result = t.aggregate({$group: {_id: 0, res: {$sum: expression}}}).toArray();
    assert.eq(result, [{_id: 0, res: expected}]);
}

// basics
test('$two', 2);
test('$$CURRENT.two', 2);
test('$$ROOT.two', 2);

// using sub expressions
test({$add: ['$two', '$$CURRENT.three']}, 5);
test({$add: ['$$CURRENT.two', '$$ROOT.nested.four']}, 6);

// $let simple
test({$let: {vars: {a: 10}, in: '$$a'}}, 10);
test({$let: {vars: {a: '$zero'}, in: '$$a'}}, 0);
test({$let: {vars: {a: {$add: ['$one', '$two']}, b: 10}, in: {$multiply: ['$$a', '$$b']}}}, 30);

// $let changing CURRENT
test({$let: {vars: {CURRENT: '$$ROOT.nested'}, in: {$multiply: ['$four', '$$ROOT.two']}}}, 8);
test(
    {
      $let: {
          vars: {CURRENT: '$$CURRENT.nested'},  // using original value of CURRENT
          in: {$multiply: ['$four', '$$ROOT.two']}
      }
    },
    8);
test(
    {
      $let: {
          vars: {CURRENT: '$nested'},  // same as last
          in: {$multiply: ['$four', '$$ROOT.two']}
      }
    },
    8);
test(
    {
      $let: {
          vars: {CURRENT: {$const: {ten: 10}}},  // "artificial" object
          in: {$multiply: ['$ten', '$$ROOT.two']}
      }
    },
    20);
test(
    {
      $let: {
          vars: {CURRENT: '$three'},  // sets current to the number 3 (not an object)
          in: {$multiply: ['$$CURRENT', '$$ROOT.two']}
      }
    },
    6);

// swapping with $let (ensures there is no ordering dependency in vars)
test(
    {
      $let: {
          vars: {x: 6, y: 10},
          in: {
              $let: {
                  vars: {x: '$$y', y: '$$x'},  // now {x:10, y:6}
                  in: {$subtract: ['$$x', '$$y']}
              }
          }
      }
    },   // not commutative!
    4);  // 10-6 not 6-10 or 6-6

// unicode is allowed
test({$let: {vars: {'日本語': 10}, in: '$$日本語'}}, 10);  // Japanese for "Japanese language"

// Can use ROOT and CURRENT directly with no subfield (SERVER-5916)
t.drop();
t.insert({_id: 'obj'});
assert.eq(t.aggregate({$project: {_id: 0, obj: '$$ROOT'}}).toArray(), [{obj: {_id: 'obj'}}]);
assert.eq(t.aggregate({$project: {_id: 0, obj: '$$CURRENT'}}).toArray(), [{obj: {_id: 'obj'}}]);
assert.eq(t.aggregate({$group: {_id: 0, objs: {$push: '$$ROOT'}}}).toArray(),
              [{_id: 0, objs: [{_id: 'obj'}]}]);
assert.eq(t.aggregate({$group: {_id: 0, objs: {$push: '$$CURRENT'}}}).toArray(),
              [{_id: 0, objs: [{_id: 'obj'}]}]);

// check name validity checks
assertErrorCode(t, {$project: {a: {$let: {vars: {ROOT: 1}, in: '$$ROOT'}}}}, 16867);
assertErrorCode(t, {$project: {a: {$let: {vars: {FOO: 1}, in: '$$FOO'}}}}, 16867);
assertErrorCode(t, {$project: {a: {$let: {vars: {_underbar: 1}, in: '$$FOO'}}}}, 16867);
assertErrorCode(t, {$project: {a: {$let: {vars: {'a.b': 1}, in: '$$FOO'}}}}, 16868);
assertErrorCode(t, {$project: {a: {$let: {vars: {'a b': 1}, in: '$$FOO'}}}}, 16868);
assertErrorCode(t, {$project: {a: '$$_underbar'}}, 16870);
assertErrorCode(t, {$project: {a: '$$with spaces'}}, 16871);