1 // expression_parser.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/base/status.h" 36 #include "mongo/base/status_with.h" 37 #include "mongo/db/matcher/expression.h" 38 #include "mongo/db/matcher/expression_leaf.h" 39 #include "mongo/db/matcher/expression_tree.h" 40 #include "mongo/db/matcher/expression_type.h" 41 #include "mongo/db/matcher/expression_with_placeholder.h" 42 #include "mongo/db/matcher/extensions_callback.h" 43 #include "mongo/db/matcher/extensions_callback_noop.h" 44 #include "mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h" 45 #include "mongo/db/pipeline/expression.h" 46 #include "mongo/db/pipeline/expression_context.h" 47 #include "mongo/stdx/functional.h" 48 49 namespace mongo { 50 51 class OperationContext; 52 53 enum class PathAcceptingKeyword { 54 ALL, 55 BITS_ALL_CLEAR, 56 BITS_ALL_SET, 57 BITS_ANY_CLEAR, 58 BITS_ANY_SET, 59 ELEM_MATCH, 60 EQUALITY, 61 EXISTS, 62 GEO_INTERSECTS, 63 GEO_NEAR, 64 GREATER_THAN, 65 GREATER_THAN_OR_EQUAL, 66 INTERNAL_EXPR_EQ, 67 INTERNAL_SCHEMA_ALL_ELEM_MATCH_FROM_INDEX, 68 INTERNAL_SCHEMA_EQ, 69 INTERNAL_SCHEMA_FMOD, 70 INTERNAL_SCHEMA_MATCH_ARRAY_INDEX, 71 INTERNAL_SCHEMA_MAX_ITEMS, 72 INTERNAL_SCHEMA_MAX_LENGTH, 73 INTERNAL_SCHEMA_MIN_ITEMS, 74 INTERNAL_SCHEMA_MIN_LENGTH, 75 INTERNAL_SCHEMA_OBJECT_MATCH, 76 INTERNAL_SCHEMA_TYPE, 77 INTERNAL_SCHEMA_UNIQUE_ITEMS, 78 IN_EXPR, 79 LESS_THAN, 80 LESS_THAN_OR_EQUAL, 81 MOD, 82 NOT_EQUAL, 83 NOT_IN, 84 OPTIONS, 85 REGEX, 86 SIZE, 87 TYPE, 88 WITHIN, 89 }; 90 91 class MatchExpressionParser { 92 public: 93 /** 94 * Features allowed in match expression parsing. 95 */ 96 enum AllowedFeatures { 97 kText = 1, 98 kGeoNear = 1 << 1, 99 kJavascript = 1 << 2, 100 kExpr = 1 << 3, 101 kJSONSchema = 1 << 4, 102 kIsolated = 1 << 5, 103 }; 104 using AllowedFeatureSet = unsigned long long; 105 static constexpr AllowedFeatureSet kBanAllSpecialFeatures = 0; 106 static constexpr AllowedFeatureSet kAllowAllSpecialFeatures = 107 std::numeric_limits<unsigned long long>::max(); 108 static constexpr AllowedFeatureSet kDefaultSpecialFeatures = 109 AllowedFeatures::kExpr | AllowedFeatures::kJSONSchema; 110 111 /** 112 * Constant double representation of 2^63. 113 */ 114 static const double kLongLongMaxPlusOneAsDouble; 115 116 /** 117 * Parses PathAcceptingKeyword from 'typeElem'. Returns 'defaultKeyword' if 'typeElem' 118 * doesn't represent a known type, or represents PathAcceptingKeyword::EQUALITY which is not 119 * handled by this parser (see SERVER-19565). 120 */ 121 static boost::optional<PathAcceptingKeyword> parsePathAcceptingKeyword( 122 BSONElement typeElem, boost::optional<PathAcceptingKeyword> defaultKeyword = boost::none); 123 124 /** 125 * Caller has to maintain ownership of 'obj'. 126 * The tree has views (BSONElement) into 'obj'. 127 */ 128 static StatusWithMatchExpression parse( 129 const BSONObj& obj, 130 const boost::intrusive_ptr<ExpressionContext>& expCtx, 131 const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(), 132 AllowedFeatureSet allowedFeatures = kDefaultSpecialFeatures); 133 134 /** 135 * Parses a BSONElement of any numeric type into a positive long long, failing if the value 136 * is any of the following: 137 * 138 * - NaN. 139 * - Negative. 140 * - A floating point number which is not integral. 141 * - Too large to fit within a 64-bit signed integer. 142 */ 143 static StatusWith<long long> parseIntegerElementToNonNegativeLong(BSONElement elem); 144 145 /** 146 * Parses a BSONElement of any numeric type into a long long, failing if the value 147 * is any of the following: 148 * 149 * - NaN. 150 * - A floating point number which is not integral. 151 * - Too large in the positive or negative direction to fit within a 64-bit signed integer. 152 */ 153 static StatusWith<long long> parseIntegerElementToLong(BSONElement elem); 154 155 /** 156 * Parses a BSONElement of any numeric type into an integer, failing if the value is: 157 * 158 * - NaN 159 * - a non-integral number 160 * - too large in the positive or negative direction to fit in an int 161 */ 162 static StatusWith<int> parseIntegerElementToInt(BSONElement elem); 163 }; 164 } // namespace mongo 165