1 // expression_array.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 <vector> 36 37 #include "mongo/base/status.h" 38 #include "mongo/bson/bsonmisc.h" 39 #include "mongo/bson/bsonobj.h" 40 #include "mongo/db/matcher/expression_path.h" 41 42 namespace mongo { 43 44 /** 45 * A path match expression which does not expand arrays at the end of the path, and which only 46 * matches if the path contains an array. 47 */ 48 class ArrayMatchingMatchExpression : public PathMatchExpression { 49 public: ArrayMatchingMatchExpression(MatchType matchType)50 ArrayMatchingMatchExpression(MatchType matchType) 51 : PathMatchExpression(matchType, 52 ElementPath::LeafArrayBehavior::kNoTraversal, 53 ElementPath::NonLeafArrayBehavior::kTraverse) {} 54 ~ArrayMatchingMatchExpression()55 virtual ~ArrayMatchingMatchExpression() {} 56 57 /** 58 * Returns whether or not the nested array, represented as the object 'anArray', matches. 59 * 60 * 'anArray' must be the nested array at this expression's path. 61 */ 62 virtual bool matchesArray(const BSONObj& anArray, MatchDetails* details) const = 0; 63 64 bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final; 65 66 bool equivalent(const MatchExpression* other) const override; 67 getCategory()68 MatchCategory getCategory() const final { 69 return MatchCategory::kArrayMatching; 70 } 71 }; 72 73 class ElemMatchObjectMatchExpression : public ArrayMatchingMatchExpression { 74 public: ElemMatchObjectMatchExpression()75 ElemMatchObjectMatchExpression() : ArrayMatchingMatchExpression(ELEM_MATCH_OBJECT) {} 76 Status init(StringData path, MatchExpression* sub); 77 78 bool matchesArray(const BSONObj& anArray, MatchDetails* details) const; 79 shallowClone()80 virtual std::unique_ptr<MatchExpression> shallowClone() const { 81 std::unique_ptr<ElemMatchObjectMatchExpression> e = 82 stdx::make_unique<ElemMatchObjectMatchExpression>(); 83 e->init(path(), _sub->shallowClone().release()).transitional_ignore(); 84 if (getTag()) { 85 e->setTag(getTag()->clone()); 86 } 87 return std::move(e); 88 } 89 90 virtual void debugString(StringBuilder& debug, int level) const; 91 92 virtual void serialize(BSONObjBuilder* out) const; 93 getChildVector()94 std::vector<MatchExpression*>* getChildVector() final { 95 return nullptr; 96 } 97 numChildren()98 virtual size_t numChildren() const { 99 return 1; 100 } 101 getChild(size_t i)102 virtual MatchExpression* getChild(size_t i) const { 103 return _sub.get(); 104 } 105 releaseChild()106 std::unique_ptr<MatchExpression> releaseChild() { 107 return std::move(_sub); 108 } 109 resetChild(std::unique_ptr<MatchExpression> newChild)110 void resetChild(std::unique_ptr<MatchExpression> newChild) { 111 _sub = std::move(newChild); 112 } 113 114 private: 115 ExpressionOptimizerFunc getOptimizer() const final; 116 117 std::unique_ptr<MatchExpression> _sub; 118 }; 119 120 class ElemMatchValueMatchExpression : public ArrayMatchingMatchExpression { 121 public: ElemMatchValueMatchExpression()122 ElemMatchValueMatchExpression() : ArrayMatchingMatchExpression(ELEM_MATCH_VALUE) {} 123 virtual ~ElemMatchValueMatchExpression(); 124 125 Status init(StringData path); 126 Status init(StringData path, MatchExpression* sub); 127 void add(MatchExpression* sub); 128 129 bool matchesArray(const BSONObj& anArray, MatchDetails* details) const; 130 shallowClone()131 virtual std::unique_ptr<MatchExpression> shallowClone() const { 132 std::unique_ptr<ElemMatchValueMatchExpression> e = 133 stdx::make_unique<ElemMatchValueMatchExpression>(); 134 e->init(path()).transitional_ignore(); 135 for (size_t i = 0; i < _subs.size(); ++i) { 136 e->add(_subs[i]->shallowClone().release()); 137 } 138 if (getTag()) { 139 e->setTag(getTag()->clone()); 140 } 141 return std::move(e); 142 } 143 144 virtual void debugString(StringBuilder& debug, int level) const; 145 146 virtual void serialize(BSONObjBuilder* out) const; 147 getChildVector()148 virtual std::vector<MatchExpression*>* getChildVector() { 149 return &_subs; 150 } 151 numChildren()152 virtual size_t numChildren() const { 153 return _subs.size(); 154 } 155 getChild(size_t i)156 virtual MatchExpression* getChild(size_t i) const { 157 return _subs[i]; 158 } 159 160 private: 161 ExpressionOptimizerFunc getOptimizer() const final; 162 163 bool _arrayElementMatchesAll(const BSONElement& e) const; 164 165 std::vector<MatchExpression*> _subs; 166 }; 167 168 class SizeMatchExpression : public ArrayMatchingMatchExpression { 169 public: SizeMatchExpression()170 SizeMatchExpression() : ArrayMatchingMatchExpression(SIZE) {} 171 Status init(StringData path, int size); 172 shallowClone()173 virtual std::unique_ptr<MatchExpression> shallowClone() const { 174 std::unique_ptr<SizeMatchExpression> e = stdx::make_unique<SizeMatchExpression>(); 175 e->init(path(), _size).transitional_ignore(); 176 if (getTag()) { 177 e->setTag(getTag()->clone()); 178 } 179 return std::move(e); 180 } 181 numChildren()182 size_t numChildren() const override { 183 return 0; 184 } 185 getChild(size_t i)186 MatchExpression* getChild(size_t i) const override { 187 return nullptr; 188 } 189 getChildVector()190 std::vector<MatchExpression*>* getChildVector() final { 191 return nullptr; 192 } 193 194 virtual bool matchesArray(const BSONObj& anArray, MatchDetails* details) const; 195 196 virtual void debugString(StringBuilder& debug, int level) const; 197 198 virtual void serialize(BSONObjBuilder* out) const; 199 200 virtual bool equivalent(const MatchExpression* other) const; 201 getData()202 int getData() const { 203 return _size; 204 } 205 206 private: getOptimizer()207 virtual ExpressionOptimizerFunc getOptimizer() const final { 208 return [](std::unique_ptr<MatchExpression> expression) { return expression; }; 209 } 210 211 int _size; // >= 0 real, < 0, nothing will match 212 }; 213 } 214