1 // expression_tree.h
2 
3 
4 /**
5  *    Copyright (C) 2018-present MongoDB, Inc.
6  *
7  *    This program is free software: you can redistribute it and/or modify
8  *    it under the terms of the Server Side Public License, version 1,
9  *    as published by MongoDB, Inc.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    Server Side Public License for more details.
15  *
16  *    You should have received a copy of the Server Side Public License
17  *    along with this program. If not, see
18  *    <http://www.mongodb.com/licensing/server-side-public-license>.
19  *
20  *    As a special exception, the copyright holders give permission to link the
21  *    code of portions of this program with the OpenSSL library under certain
22  *    conditions as described in each individual source file and distribute
23  *    linked combinations including the program with the OpenSSL library. You
24  *    must comply with the Server Side Public License in all respects for
25  *    all of the code used other than as permitted herein. If you modify file(s)
26  *    with this exception, you may extend this exception to your version of the
27  *    file(s), but you are not obligated to do so. If you do not wish to do so,
28  *    delete this exception statement from your version. If you delete this
29  *    exception statement from all source files in the program, then also delete
30  *    it in the license file.
31  */
32 
33 #pragma once
34 
35 #include "mongo/db/matcher/expression.h"
36 
37 
38 /**
39  * this contains all Expessions that define the structure of the tree
40  * they do not look at the structure of the documents themselves, just combine other things
41  */
42 namespace mongo {
43 
44 class ListOfMatchExpression : public MatchExpression {
45 public:
ListOfMatchExpression(MatchType type)46     ListOfMatchExpression(MatchType type) : MatchExpression(type) {}
47     virtual ~ListOfMatchExpression();
48 
49     /**
50      * @param e - I take ownership
51      */
52     void add(MatchExpression* e);
53 
54     /**
55      * clears all the thingsd we own, and does NOT delete
56      * someone else has taken ownership
57      */
clearAndRelease()58     void clearAndRelease() {
59         _expressions.clear();
60     }
61 
numChildren()62     virtual size_t numChildren() const {
63         return _expressions.size();
64     }
65 
getChild(size_t i)66     virtual MatchExpression* getChild(size_t i) const {
67         return _expressions[i];
68     }
69 
70     /*
71      * Replaces the ith child with nullptr, and releases ownership of the child.
72      */
releaseChild(size_t i)73     virtual std::unique_ptr<MatchExpression> releaseChild(size_t i) {
74         auto child = std::unique_ptr<MatchExpression>(_expressions[i]);
75         _expressions[i] = nullptr;
76         return child;
77     }
78 
79     /*
80      * Removes the ith child, and releases ownership of the child.
81      */
removeChild(size_t i)82     virtual std::unique_ptr<MatchExpression> removeChild(size_t i) {
83         auto child = std::unique_ptr<MatchExpression>(_expressions[i]);
84         _expressions.erase(_expressions.begin() + i);
85         return child;
86     }
87 
getChildVector()88     virtual std::vector<MatchExpression*>* getChildVector() {
89         return &_expressions;
90     }
91 
92     bool equivalent(const MatchExpression* other) const;
93 
getCategory()94     MatchCategory getCategory() const final {
95         return MatchCategory::kLogical;
96     }
97 
98 protected:
99     void _debugList(StringBuilder& debug, int level) const;
100 
101     void _listToBSON(BSONArrayBuilder* out) const;
102 
103 private:
104     ExpressionOptimizerFunc getOptimizer() const final;
105 
106     std::vector<MatchExpression*> _expressions;
107 };
108 
109 class AndMatchExpression : public ListOfMatchExpression {
110 public:
111     static constexpr StringData kName = "$and"_sd;
112 
AndMatchExpression()113     AndMatchExpression() : ListOfMatchExpression(AND) {}
~AndMatchExpression()114     virtual ~AndMatchExpression() {}
115 
116     virtual bool matches(const MatchableDocument* doc, MatchDetails* details = 0) const;
117 
118     bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final;
119 
shallowClone()120     virtual std::unique_ptr<MatchExpression> shallowClone() const {
121         std::unique_ptr<AndMatchExpression> self = stdx::make_unique<AndMatchExpression>();
122         for (size_t i = 0; i < numChildren(); ++i) {
123             self->add(getChild(i)->shallowClone().release());
124         }
125         if (getTag()) {
126             self->setTag(getTag()->clone());
127         }
128         return std::move(self);
129     }
130 
131     virtual void debugString(StringBuilder& debug, int level = 0) const;
132 
133     virtual void serialize(BSONObjBuilder* out) const;
134 };
135 
136 class OrMatchExpression : public ListOfMatchExpression {
137 public:
138     static constexpr StringData kName = "$or"_sd;
139 
OrMatchExpression()140     OrMatchExpression() : ListOfMatchExpression(OR) {}
~OrMatchExpression()141     virtual ~OrMatchExpression() {}
142 
143     virtual bool matches(const MatchableDocument* doc, MatchDetails* details = 0) const;
144 
145     bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final;
146 
shallowClone()147     virtual std::unique_ptr<MatchExpression> shallowClone() const {
148         std::unique_ptr<OrMatchExpression> self = stdx::make_unique<OrMatchExpression>();
149         for (size_t i = 0; i < numChildren(); ++i) {
150             self->add(getChild(i)->shallowClone().release());
151         }
152         if (getTag()) {
153             self->setTag(getTag()->clone());
154         }
155         return std::move(self);
156     }
157 
158     virtual void debugString(StringBuilder& debug, int level = 0) const;
159 
160     virtual void serialize(BSONObjBuilder* out) const;
161 };
162 
163 class NorMatchExpression : public ListOfMatchExpression {
164 public:
165     static constexpr StringData kName = "$nor"_sd;
166 
NorMatchExpression()167     NorMatchExpression() : ListOfMatchExpression(NOR) {}
~NorMatchExpression()168     virtual ~NorMatchExpression() {}
169 
170     virtual bool matches(const MatchableDocument* doc, MatchDetails* details = 0) const;
171 
172     bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final;
173 
shallowClone()174     virtual std::unique_ptr<MatchExpression> shallowClone() const {
175         std::unique_ptr<NorMatchExpression> self = stdx::make_unique<NorMatchExpression>();
176         for (size_t i = 0; i < numChildren(); ++i) {
177             self->add(getChild(i)->shallowClone().release());
178         }
179         if (getTag()) {
180             self->setTag(getTag()->clone());
181         }
182         return std::move(self);
183     }
184 
185     virtual void debugString(StringBuilder& debug, int level = 0) const;
186 
187     virtual void serialize(BSONObjBuilder* out) const;
188 };
189 
190 class NotMatchExpression final : public MatchExpression {
191 public:
NotMatchExpression()192     NotMatchExpression() : MatchExpression(NOT) {}
NotMatchExpression(MatchExpression * e)193     NotMatchExpression(MatchExpression* e) : MatchExpression(NOT), _exp(e) {}
194     /**
195      * @param exp - I own it, and will delete
196      */
init(MatchExpression * exp)197     virtual Status init(MatchExpression* exp) {
198         _exp.reset(exp);
199         return Status::OK();
200     }
201 
shallowClone()202     virtual std::unique_ptr<MatchExpression> shallowClone() const {
203         std::unique_ptr<NotMatchExpression> self = stdx::make_unique<NotMatchExpression>();
204         self->init(_exp->shallowClone().release()).transitional_ignore();
205         if (getTag()) {
206             self->setTag(getTag()->clone());
207         }
208         return std::move(self);
209     }
210 
211     virtual bool matches(const MatchableDocument* doc, MatchDetails* details = 0) const {
212         return !_exp->matches(doc, NULL);
213     }
214 
215     bool matchesSingleElement(const BSONElement& elt, MatchDetails* details = nullptr) const final {
216         return !_exp->matchesSingleElement(elt, details);
217     }
218 
219     virtual void debugString(StringBuilder& debug, int level = 0) const;
220 
221     virtual void serialize(BSONObjBuilder* out) const;
222 
223     bool equivalent(const MatchExpression* other) const;
224 
numChildren()225     size_t numChildren() const final {
226         return 1;
227     }
228 
getChild(size_t i)229     MatchExpression* getChild(size_t i) const final {
230         return _exp.get();
231     }
232 
getChildVector()233     std::vector<MatchExpression*>* getChildVector() final {
234         return nullptr;
235     }
236 
releaseChild(void)237     MatchExpression* releaseChild(void) {
238         return _exp.release();
239     }
240 
resetChild(MatchExpression * newChild)241     void resetChild(MatchExpression* newChild) {
242         _exp.reset(newChild);
243     }
244 
getCategory()245     MatchCategory getCategory() const final {
246         return MatchCategory::kLogical;
247     }
248 
249 private:
250     ExpressionOptimizerFunc getOptimizer() const final;
251 
252     std::unique_ptr<MatchExpression> _exp;
253 };
254 }
255