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