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