1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include "mongo/db/pipeline/document.h"
34 #include "mongo/stdx/memory.h"
35 #include "mongo/stdx/unordered_map.h"
36 #include "mongo/util/string_map.h"
37 
38 namespace mongo {
39 
40 /**
41  * The state used as input and working space for Expressions.
42  */
43 class Variables final {
44 public:
45     // Each unique variable is assigned a unique id of this type. Negative ids are reserved for
46     // system variables and non-negative ids are allocated for user variables.
47     using Id = int64_t;
48 
49     /**
50      * Generates Variables::Id and keeps track of the number of Ids handed out. Each successive Id
51      * generated by an instance of this class must be greater than all preceding Ids.
52      */
53     class IdGenerator {
54     public:
IdGenerator()55         IdGenerator() : _nextId(0) {}
56 
generateId()57         Variables::Id generateId() {
58             return _nextId++;
59         }
60 
61     private:
62         Variables::Id _nextId;
63     };
64 
65     Variables() = default;
66 
67     static void uassertValidNameForUserWrite(StringData varName);
68     static void uassertValidNameForUserRead(StringData varName);
69 
isUserDefinedVariable(Variables::Id id)70     static bool isUserDefinedVariable(Variables::Id id) {
71         return id >= 0;
72     }
73 
74     // Ids for builtin variables.
75     static constexpr Variables::Id kRootId = Id(-1);
76     static constexpr Variables::Id kRemoveId = Id(-2);
77 
78     // Map from builtin var name to reserved id number.
79     static const StringMap<Id> kBuiltinVarNameToId;
80 
81     /**
82      * Sets the value of a user-defined variable. Illegal to use with the reserved builtin variables
83      * defined above.
84      */
85     void setValue(Variables::Id id, const Value& value);
86 
87     /**
88      * Same as 'setValue' but marks 'value' as being constant. It is illegal to change a value that
89      * has been marked constant.
90      */
91     void setConstantValue(Variables::Id id, const Value& value);
92 
93     /**
94      * Gets the value of a user-defined or system variable. If the 'id' provided represents the
95      * special ROOT variable, then we return 'root' in Value form.
96      */
97     Value getValue(Variables::Id id, const Document& root) const;
98 
99     /**
100      * Gets the value of a user-defined variable. Should only be called when we know 'id' represents
101      * a user-defined variable.
102      */
103     Value getUserDefinedValue(Variables::Id id) const;
104 
105     /**
106      * Returns whether a constant value for 'id' has been defined using setConstantValue().
107      */
hasConstantValue(Variables::Id id)108     bool hasConstantValue(Variables::Id id) const {
109 
110         return _valueList.size() > static_cast<size_t>(id) && _valueList[id].isConstant;
111     }
112 
113     /**
114      * Returns Document() for non-document values, but otherwise identical to getValue(). If the
115      * 'id' provided represents the special ROOT variable, then we return 'root'.
116      */
117     Document getDocument(Variables::Id id, const Document& root) const;
118 
useIdGenerator()119     IdGenerator* useIdGenerator() {
120         return &_idGenerator;
121     }
122 
123 private:
124     struct ValueAndState {
125         ValueAndState() = default;
126 
ValueAndStateValueAndState127         ValueAndState(Value val, bool isConst) : value(std::move(val)), isConstant(isConst) {}
128 
129         Value value;
130         bool isConstant = false;
131     };
132 
133     void setValue(Id id, const Value& value, bool isConstant);
134 
135     IdGenerator _idGenerator;
136     std::vector<ValueAndState> _valueList;
137 };
138 
139 /**
140  * This class represents the Variables that are defined in an Expression tree.
141  *
142  * All copies from a given instance share enough information to ensure unique Ids are assigned
143  * and to propagate back to the original instance enough information to correctly construct a
144  * Variables instance.
145  */
146 class VariablesParseState final {
147 public:
VariablesParseState(Variables::IdGenerator * variableIdGenerator)148     explicit VariablesParseState(Variables::IdGenerator* variableIdGenerator)
149         : _idGenerator(variableIdGenerator) {}
150 
151     /**
152      * Assigns a named variable a unique Id. This differs from all other variables, even
153      * others with the same name.
154      *
155      * The special variables ROOT and CURRENT are always implicitly defined with CURRENT
156      * equivalent to ROOT. If CURRENT is explicitly defined by a call to this function, it
157      * breaks that equivalence.
158      *
159      * NOTE: Name validation is responsibility of caller.
160      */
161     Variables::Id defineVariable(StringData name);
162 
163     /**
164      * Returns true if there are any variables defined in this scope.
165      */
hasDefinedVariables()166     bool hasDefinedVariables() const {
167         return !_variables.empty();
168     }
169 
170     /**
171      * Returns the current Id for a variable. uasserts if the variable isn't defined.
172      */
173     Variables::Id getVariable(StringData name) const;
174 
175     /**
176      * Returns the set of variable IDs defined at this scope.
177      */
178     std::set<Variables::Id> getDefinedVariableIDs() const;
179 
180     /**
181      * Return a copy of this VariablesParseState. Will replace the copy's '_idGenerator' pointer
182      * with 'idGenerator'.
183      */
copyWith(Variables::IdGenerator * idGenerator)184     VariablesParseState copyWith(Variables::IdGenerator* idGenerator) const {
185         VariablesParseState vps = *this;
186         vps._idGenerator = idGenerator;
187         return vps;
188     }
189 
190 private:
191     // Not owned here.
192     Variables::IdGenerator* _idGenerator;
193 
194     StringMap<Variables::Id> _variables;
195     Variables::Id _lastSeen = -1;
196 };
197 
198 }  // namespace mongo
199