summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2017-08-21 15:31:06 -0400
committerTess Avitabile <tess.avitabile@mongodb.com>2017-08-25 14:16:10 -0400
commitb19f95495d1df437722e6a0c85ea5ca6f91cdd8b (patch)
treebbc5dd0a3b5868240cd6c5c97c48408e3170046f
parent529d5de71344fda500802fa4a8671c5745ad62fa (diff)
downloadmongo-b19f95495d1df437722e6a0c85ea5ca6f91cdd8b.tar.gz
SERVER-29840 Add allowed features bitmask to MatchExpressionParser::parse
-rw-r--r--jstests/aggregation/bugs/match.js4
-rw-r--r--jstests/aggregation/bugs/server6335.js4
-rw-r--r--jstests/aggregation/bugs/server6530.js5
-rw-r--r--jstests/aggregation/sources/graphLookup/error.js16
-rw-r--r--jstests/core/doc_validation_invalid_validators.js4
-rw-r--r--jstests/core/list_collections_filter.js19
-rw-r--r--jstests/core/list_databases.js16
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp4
-rw-r--r--src/mongo/db/catalog/collection.cpp1
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp32
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp5
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp5
-rw-r--r--src/mongo/db/commands/apply_ops_cmd.cpp1
-rw-r--r--src/mongo/db/commands/dbcommands.cpp4
-rw-r--r--src/mongo/db/commands/find_cmd.cpp17
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp9
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp9
-rw-r--r--src/mongo/db/commands/index_filter_commands_test.cpp10
-rw-r--r--src/mongo/db/commands/list_collections.cpp5
-rw-r--r--src/mongo/db/commands/list_databases.cpp4
-rw-r--r--src/mongo/db/commands/mr.cpp20
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp9
-rw-r--r--src/mongo/db/commands/plan_cache_commands_test.cpp31
-rw-r--r--src/mongo/db/dbhelpers.cpp9
-rw-r--r--src/mongo/db/exec/projection.cpp3
-rw-r--r--src/mongo/db/exec/projection.h6
-rw-r--r--src/mongo/db/exec/projection_exec.cpp5
-rw-r--r--src/mongo/db/exec/projection_exec.h3
-rw-r--r--src/mongo/db/exec/projection_exec_test.cpp12
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp8
-rw-r--r--src/mongo/db/exec/subplan.cpp5
-rw-r--r--src/mongo/db/matcher/SConscript1
-rw-r--r--src/mongo/db/matcher/copyable_match_expression.h28
-rw-r--r--src/mongo/db/matcher/expression_algo_test.cpp88
-rw-r--r--src/mongo/db/matcher/expression_geo_test.cpp1
-rw-r--r--src/mongo/db/matcher/expression_parser.cpp142
-rw-r--r--src/mongo/db/matcher/expression_parser.h49
-rw-r--r--src/mongo/db/matcher/expression_parser_array_test.cpp135
-rw-r--r--src/mongo/db/matcher/expression_parser_geo_test.cpp238
-rw-r--r--src/mongo/db/matcher/expression_parser_leaf_test.cpp1134
-rw-r--r--src/mongo/db/matcher/expression_parser_test.cpp157
-rw-r--r--src/mongo/db/matcher/expression_parser_tree.cpp8
-rw-r--r--src/mongo/db/matcher/expression_parser_tree_test.cpp19
-rw-r--r--src/mongo/db/matcher/expression_serialization_test.cpp980
-rw-r--r--src/mongo/db/matcher/expression_text.h15
-rw-r--r--src/mongo/db/matcher/expression_text_base.h15
-rw-r--r--src/mongo/db/matcher/expression_text_noop.h4
-rw-r--r--src/mongo/db/matcher/expression_where_noop.cpp2
-rw-r--r--src/mongo/db/matcher/expression_with_placeholder.cpp5
-rw-r--r--src/mongo/db/matcher/expression_with_placeholder_test.cpp16
-rw-r--r--src/mongo/db/matcher/extensions_callback_disallow_extensions.cpp44
-rw-r--r--src/mongo/db/matcher/extensions_callback_disallow_extensions.h53
-rw-r--r--src/mongo/db/matcher/matcher.cpp8
-rw-r--r--src/mongo/db/matcher/matcher.h8
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp19
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp16
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp25
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp28
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp10
-rw-r--r--src/mongo/db/matcher/schema/expression_parser_schema_test.cpp397
-rw-r--r--src/mongo/db/ops/modifier_pull.cpp6
-rw-r--r--src/mongo/db/ops/modifier_pull_test.cpp68
-rw-r--r--src/mongo/db/ops/parsed_delete.cpp9
-rw-r--r--src/mongo/db/ops/parsed_update.cpp9
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.cpp14
-rw-r--r--src/mongo/db/pipeline/document_source_match.cpp37
-rw-r--r--src/mongo/db/pipeline/document_source_match_test.cpp18
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp7
-rw-r--r--src/mongo/db/query/canonical_query.cpp42
-rw-r--r--src/mongo/db/query/canonical_query.h35
-rw-r--r--src/mongo/db/query/canonical_query_test.cpp48
-rw-r--r--src/mongo/db/query/find.cpp10
-rw-r--r--src/mongo/db/query/get_executor.cpp32
-rw-r--r--src/mongo/db/query/get_executor_test.cpp4
-rw-r--r--src/mongo/db/query/index_bounds_builder_test.cpp4
-rw-r--r--src/mongo/db/query/parsed_distinct.cpp8
-rw-r--r--src/mongo/db/query/parsed_distinct_test.cpp10
-rw-r--r--src/mongo/db/query/parsed_projection.cpp11
-rw-r--r--src/mongo/db/query/parsed_projection.h3
-rw-r--r--src/mongo/db/query/parsed_projection_test.cpp37
-rw-r--r--src/mongo/db/query/plan_cache_indexability_test.cpp4
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp73
-rw-r--r--src/mongo/db/query/planner_ixselect_test.cpp4
-rw-r--r--src/mongo/db/query/query_planner_test.cpp10
-rw-r--r--src/mongo/db/query/query_planner_test_fixture.cpp33
-rw-r--r--src/mongo/db/query/query_planner_test_lib.cpp5
-rw-r--r--src/mongo/db/query/query_solution_test.cpp7
-rw-r--r--src/mongo/db/query/stage_builder.cpp4
-rw-r--r--src/mongo/db/repl/apply_ops.cpp8
-rw-r--r--src/mongo/db/ttl.cpp4
-rw-r--r--src/mongo/db/update/path_support_test.cpp5
-rw-r--r--src/mongo/db/update/pull_node.cpp9
-rw-r--r--src/mongo/db/update/pull_node_test.cpp112
-rw-r--r--src/mongo/db/update/update_driver.cpp8
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp4
-rw-r--r--src/mongo/dbtests/executor_registry.cpp4
-rw-r--r--src/mongo/dbtests/matchertests.cpp39
-rw-r--r--src/mongo/dbtests/oplogstarttests.cpp4
-rw-r--r--src/mongo/dbtests/plan_ranking.cpp40
-rw-r--r--src/mongo/dbtests/query_plan_executor.cpp7
-rw-r--r--src/mongo/dbtests/query_stage_cached_plan.cpp7
-rw-r--r--src/mongo/dbtests/query_stage_collscan.cpp5
-rw-r--r--src/mongo/dbtests/query_stage_count.cpp5
-rw-r--r--src/mongo/dbtests/query_stage_delete.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_fetch.cpp5
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp17
-rw-r--r--src/mongo/dbtests/query_stage_subplan.cpp36
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp5
-rw-r--r--src/mongo/dbtests/query_stage_update.cpp4
-rw-r--r--src/mongo/s/chunk_manager.cpp10
-rw-r--r--src/mongo/s/chunk_manager_index_bounds_test.cpp11
-rw-r--r--src/mongo/s/commands/chunk_manager_targeter.cpp16
-rw-r--r--src/mongo/s/commands/cluster_find_cmd.cpp9
-rw-r--r--src/mongo/s/commands/strategy.cpp10
-rw-r--r--src/mongo/s/shard_key_pattern.cpp8
116 files changed, 2685 insertions, 2203 deletions
diff --git a/jstests/aggregation/bugs/match.js b/jstests/aggregation/bugs/match.js
index 2ee646dac7e..0d08c0744b8 100644
--- a/jstests/aggregation/bugs/match.js
+++ b/jstests/aggregation/bugs/match.js
@@ -51,10 +51,10 @@ function assertResults(expectedResults, matchSpec) {
assertError(2, {a: {$mod: [0 /* invalid */, 0]}});
// $where not allowed.
-assertError(16395, {$where: 'true'});
+assertError(ErrorCodes.BadValue, {$where: 'true'});
// Geo not allowed.
-assertError(16424, {$match: {a: {$near: [0, 0]}}});
+assertError(ErrorCodes.BadValue, {$match: {a: {$near: [0, 0]}}});
// Update modifier not allowed.
if (0) { // SERVER-6650
diff --git a/jstests/aggregation/bugs/server6335.js b/jstests/aggregation/bugs/server6335.js
index a26568280ce..cecd00f9d4d 100644
--- a/jstests/aggregation/bugs/server6335.js
+++ b/jstests/aggregation/bugs/server6335.js
@@ -3,5 +3,5 @@
// load the test utilities
load('jstests/aggregation/extras/utils.js');
-assertErrorCode(db.foo, {$match: {$where: "return true"}}, 16395);
-assertErrorCode(db.foo, {$match: {$and: [{$where: "return true"}]}}, 16395);
+assertErrorCode(db.foo, {$match: {$where: "return true"}}, ErrorCodes.BadValue);
+assertErrorCode(db.foo, {$match: {$and: [{$where: "return true"}]}}, ErrorCodes.BadValue);
diff --git a/jstests/aggregation/bugs/server6530.js b/jstests/aggregation/bugs/server6530.js
index de2ec9c0912..22d26143e39 100644
--- a/jstests/aggregation/bugs/server6530.js
+++ b/jstests/aggregation/bugs/server6530.js
@@ -1,5 +1,6 @@
// server-6530: disallow $near queries in $match operations
load('jstests/aggregation/extras/utils.js');
-assertErrorCode(db.foo, {$match: {$near: [0, 0]}}, 16424);
-assertErrorCode(db.foo, {$match: {$nearSphere: [2, 2]}}, 16426);
+assertErrorCode(db.foo, {$match: {$near: [0, 0]}}, ErrorCodes.BadValue);
+assertErrorCode(db.foo, {$match: {$nearSphere: [2, 2]}}, ErrorCodes.BadValue);
+assertErrorCode(db.foo, {$match: {$geoNear: [2, 2]}}, ErrorCodes.BadValue);
diff --git a/jstests/aggregation/sources/graphLookup/error.js b/jstests/aggregation/sources/graphLookup/error.js
index 3ed81a9345d..ab09a851f5d 100644
--- a/jstests/aggregation/sources/graphLookup/error.js
+++ b/jstests/aggregation/sources/graphLookup/error.js
@@ -272,7 +272,7 @@ load("jstests/aggregation/extras/utils.js"); // For "assertErrorCode".
}
}
};
- assertErrorCode(local, pipeline, 40187, "cannot use $near inside $graphLookup");
+ assertErrorCode(local, pipeline, 40186, "cannot use $near inside $graphLookup");
pipeline = {
$graphLookup: {
@@ -293,7 +293,19 @@ load("jstests/aggregation/extras/utils.js"); // For "assertErrorCode".
}
}
};
- assertErrorCode(local, pipeline, 40187, "cannot use $near inside $graphLookup at any depth");
+ assertErrorCode(local, pipeline, 40186, "cannot use $near inside $graphLookup at any depth");
+
+ pipeline = {
+ $graphLookup: {
+ from: 'foreign',
+ startWith: {$literal: 0},
+ connectToField: "a",
+ connectFromField: "b",
+ as: "output",
+ restrictSearchWithMatch: {x: {$expr: 5}}
+ }
+ };
+ assertErrorCode(local, pipeline, 40186, "cannot use $expr inside $graphLookup");
// $graphLookup can only consume at most 100MB of memory.
var foreign = db.foreign;
diff --git a/jstests/core/doc_validation_invalid_validators.js b/jstests/core/doc_validation_invalid_validators.js
index 45cfa7c2cf4..ec6ccdd7fdb 100644
--- a/jstests/core/doc_validation_invalid_validators.js
+++ b/jstests/core/doc_validation_invalid_validators.js
@@ -37,7 +37,8 @@
assert.commandWorked(db.createCollection(collName, {validator: {a: {$exists: true}}}));
// Verify some invalid match statements can't be passed to collMod.
- assert.commandFailed(db.runCommand({"collMod": collName, "validator": {$text: "bob"}}));
+ assert.commandFailed(
+ db.runCommand({"collMod": collName, "validator": {$text: {$search: "bob"}}}));
assert.commandFailed(
db.runCommand({"collMod": collName, "validator": {$where: "this.a == this.b"}}));
assert.commandFailed(
@@ -46,6 +47,7 @@
db.runCommand({"collMod": collName, "validator": {$geoNear: {place: "holder"}}}));
assert.commandFailed(
db.runCommand({"collMod": collName, "validator": {$nearSphere: {place: "holder"}}}));
+ assert.commandFailed(db.runCommand({"collMod": collName, "validator": {a: {$expr: 5}}}));
coll.drop();
diff --git a/jstests/core/list_collections_filter.js b/jstests/core/list_collections_filter.js
index e0d18f055d0..8590d6ab6cf 100644
--- a/jstests/core/list_collections_filter.js
+++ b/jstests/core/list_collections_filter.js
@@ -83,4 +83,23 @@
]
},
[]);
+
+ // No extensions are allowed in filters.
+ assert.throws(function() {
+ mydb.getCollectionInfos({$text: {$search: "str"}});
+ });
+ assert.throws(function() {
+ mydb.getCollectionInfos({
+ $where: function() {
+ return true;
+ }
+ });
+ });
+ assert.throws(function() {
+ mydb.getCollectionInfos(
+ {a: {$nearSphere: {$geometry: {type: "Point", coordinates: [0, 0]}}}});
+ });
+ assert.throws(function() {
+ mydb.getCollectionInfos({a: {$expr: 5}});
+ });
}());
diff --git a/jstests/core/list_databases.js b/jstests/core/list_databases.js
index 8ea7fbfe255..c308b0bc236 100644
--- a/jstests/core/list_databases.js
+++ b/jstests/core/list_databases.js
@@ -61,4 +61,20 @@
db.adminCommand({listDatabases: 1, nameOnly: true, filter: {name: /zap/}}));
assert.eq(1, cmdRes.databases.length, tojson(cmdRes));
verifyNameOnly(cmdRes);
+
+ // No extensions are allowed in filters.
+ assert.commandFailed(db.adminCommand({listDatabases: 1, filter: {$text: {$search: "str"}}}));
+ assert.commandFailed(db.adminCommand({
+ listDatabases: 1,
+ filter: {
+ $where: function() {
+ return true;
+ }
+ }
+ }));
+ assert.commandFailed(db.adminCommand({
+ listDatabases: 1,
+ filter: {a: {$nearSphere: {$geometry: {type: "Point", coordinates: [0, 0]}}}}
+ }));
+ assert.commandFailed(db.adminCommand({listDatabases: 1, filter: {a: {$expr: 5}}}));
}());
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.cpp b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
index c11f2df00e0..1d2c92ecd2a 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -39,7 +39,6 @@
#include "mongo/db/auth/privilege_parser.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context_noop.h"
#include "mongo/db/update/update_driver.h"
@@ -296,8 +295,7 @@ Status AuthzManagerExternalStateMock::_queryVector(
const BSONObj& query,
std::vector<BSONObjCollection::iterator>* result) {
CollatorInterface* collator = nullptr;
- StatusWithMatchExpression parseResult =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(query, collator);
if (!parseResult.isOK()) {
return parseResult.getStatus();
}
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index f3bbb12e49f..5d8e64a9bdd 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -49,7 +49,6 @@
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/keypattern.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/ops/update_request.h"
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 58b04a89122..78f2d84c0d4 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -56,7 +56,6 @@
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/keypattern.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/ops/update_request.h"
@@ -108,28 +107,6 @@ MONGO_INITIALIZER(InitializeParseValidationActionImpl)(InitializerContext* const
// Used below to fail during inserts.
MONGO_FP_DECLARE(failCollectionInserts);
-const auto bannedExpressionsInValidators = std::set<StringData>{
- "$geoNear", "$near", "$nearSphere", "$text", "$where",
-};
-
-Status checkValidatorForBannedExpressions(const BSONObj& validator) {
- for (auto field : validator) {
- const auto name = field.fieldNameStringData();
- if (name[0] == '$' && bannedExpressionsInValidators.count(name)) {
- return {ErrorCodes::InvalidOptions,
- str::stream() << name << " is not allowed in collection validators"};
- }
-
- if (field.type() == Object || field.type() == Array) {
- auto status = checkValidatorForBannedExpressions(field.Obj());
- if (!status.isOK())
- return status;
- }
- }
-
- return Status::OK();
-}
-
// Uses the collator factory to convert the BSON representation of a collator to a
// CollatorInterface. Returns null if the BSONObj is empty. We expect the stored collation to be
// valid, since it gets validated on collection create.
@@ -305,14 +282,7 @@ StatusWithMatchExpression CollectionImpl::parseValidator(const BSONObj& validato
<< " database"};
}
- {
- auto status = checkValidatorForBannedExpressions(validator);
- if (!status.isOK())
- return status;
- }
-
- auto statusWithMatcher = MatchExpressionParser::parse(
- validator, ExtensionsCallbackDisallowExtensions(), _collator.get());
+ auto statusWithMatcher = MatchExpressionParser::parse(validator, _collator.get());
if (!statusWithMatcher.isOK())
return statusWithMatcher.getStatus();
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index 5a6cb153456..7f46d56dac8 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -44,7 +44,6 @@
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/query/collation/collator_factory_interface.h"
#include "mongo/db/service_context.h"
@@ -128,8 +127,8 @@ IndexCatalogEntryImpl::IndexCatalogEntryImpl(IndexCatalogEntry* const this_,
if (BSONElement filterElement = _descriptor->getInfoElement("partialFilterExpression")) {
invariant(filterElement.isABSONObj());
BSONObj filter = filterElement.Obj();
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), _collator.get());
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filter, _collator.get());
// this should be checked in create, so can blow up here
invariantOK(statusWithMatcher.getStatus());
_filterExpression = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp
index 40f2ecb1c0d..b128061a1c1 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -55,7 +55,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/keypattern.h"
#include "mongo/db/matcher/expression.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/ops/delete.h"
#include "mongo/db/query/collation/collation_spec.h"
@@ -667,8 +666,8 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx, const BSONObj& spec)
}
// The collator must outlive the constructed MatchExpression.
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterElement.Obj(), ExtensionsCallbackDisallowExtensions(), collator.get());
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterElement.Obj(), collator.get());
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
diff --git a/src/mongo/db/commands/apply_ops_cmd.cpp b/src/mongo/db/commands/apply_ops_cmd.cpp
index 504abd19079..e2c0d9c6f4a 100644
--- a/src/mongo/db/commands/apply_ops_cmd.cpp
+++ b/src/mongo/db/commands/apply_ops_cmd.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/db_raii.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/jsobj.h"
-#include "mongo/db/matcher/matcher.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/repl/apply_ops.h"
#include "mongo/db/repl/oplog.h"
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index ef4ddac6eb1..f5cc3803928 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -74,7 +74,6 @@
#include "mongo/db/json.h"
#include "mongo/db/keypattern.h"
#include "mongo/db/lasterror.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/insert.h"
@@ -696,8 +695,7 @@ public:
qr->setFilter(query);
qr->setSort(sort);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr));
if (!statusWithCQ.isOK()) {
uasserted(17240, "Can't canonicalize query " + query.toString());
return false;
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index f54dbbbf312..fe1d0940ff9 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -151,8 +151,14 @@ public:
// Finish the parsing step by using the QueryRequest to create a CanonicalQuery.
ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx, std::move(qrStatus.getValue()), extensionsCallback);
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qrStatus.getValue()),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
}
@@ -257,7 +263,14 @@ public:
// Finish the parsing step by using the QueryRequest to create a CanonicalQuery.
ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return appendCommandStatus(result, statusWithCQ.getStatus());
}
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index 2a5c5c32d6c..02a57e7d0e8 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -215,7 +215,14 @@ public:
qr->setLimit(numWanted);
qr->setCollation(collation);
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
errmsg = "Can't parse filter / create query";
return false;
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index c7e3b2043bc..1992f122edc 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -310,7 +310,14 @@ Status ClearFilters::clear(OperationContext* opCtx,
qr->setSort(entry.sort);
qr->setProj(entry.projection);
qr->setCollation(entry.collation);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
invariantOK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp
index e182aabe539..17dec1cb003 100644
--- a/src/mongo/db/commands/index_filter_commands_test.cpp
+++ b/src/mongo/db/commands/index_filter_commands_test.cpp
@@ -33,7 +33,6 @@
#include "mongo/db/commands/index_filter_commands.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/operation_context_noop.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/plan_ranker.h"
@@ -132,8 +131,7 @@ void addQueryShapeToPlanCache(OperationContext* opCtx,
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projectionStr));
qr->setCollation(fromjson(collationStr));
- auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -162,8 +160,7 @@ bool planCacheContains(const PlanCache& planCache,
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projectionStr));
qr->setCollation(fromjson(collationStr));
- auto statusWithInputQuery = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithInputQuery = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithInputQuery.getStatus());
unique_ptr<CanonicalQuery> inputQuery = std::move(statusWithInputQuery.getValue());
@@ -183,8 +180,7 @@ bool planCacheContains(const PlanCache& planCache,
qr->setSort(entry->sort);
qr->setProj(entry->projection);
qr->setCollation(entry->collation);
- auto statusWithCurrentQuery = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCurrentQuery = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCurrentQuery.getStatus());
unique_ptr<CanonicalQuery> currentQuery = std::move(statusWithCurrentQuery.getValue());
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index 6a619a43861..c952573ac14 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -49,7 +49,6 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/exec/working_set.h"
#include "mongo/db/index/index_descriptor.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/cursor_request.h"
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/find_common.h"
@@ -245,8 +244,8 @@ public:
}
// The collator is null because collection objects are compared using binary comparison.
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterElt.Obj(), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterElt.Obj(), collator);
if (!statusWithMatcher.isOK()) {
return appendCommandStatus(result, statusWithMatcher.getStatus());
}
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp
index b25a13b887b..232803320d0 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/commands.h"
#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/matcher/expression.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/storage_engine.h"
@@ -100,8 +99,7 @@ public:
// The collator is null because database metadata objects are compared using simple
// binary comparison.
const CollatorInterface* collator = nullptr;
- auto statusWithMatcher = MatchExpressionParser::parse(
- filterElt.Obj(), ExtensionsCallbackDisallowExtensions(), collator);
+ auto statusWithMatcher = MatchExpressionParser::parse(filterElt.Obj(), collator);
if (!statusWithMatcher.isOK()) {
return appendCommandStatus(result, statusWithMatcher.getStatus());
}
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 580918250a0..3cfbad4b4c7 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -53,7 +53,6 @@
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/matcher/extensions_callback_real.h"
-#include "mongo/db/matcher/matcher.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/insert.h"
#include "mongo/db/query/find_common.h"
@@ -1096,7 +1095,14 @@ void State::finalReduce(OperationContext* opCtx, CurOp* curOp, ProgressMeterHold
auto qr = stdx::make_unique<QueryRequest>(_config.incLong);
qr->setSort(sortKey);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
verify(statusWithCQ.isOK());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -1464,8 +1470,14 @@ public:
const ExtensionsCallbackReal extensionsCallback(opCtx, &config.nss);
- auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ = CanonicalQuery::canonicalize(
+ opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
uasserted(17238, "Can't canonicalize query " + config.filter.toString());
return 0;
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index f66bc7392b2..031d59e408d 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -207,7 +207,14 @@ StatusWith<unique_ptr<CanonicalQuery>> PlanCacheCommand::canonicalize(OperationC
qr->setProj(projObj);
qr->setCollation(collationObj);
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
}
diff --git a/src/mongo/db/commands/plan_cache_commands_test.cpp b/src/mongo/db/commands/plan_cache_commands_test.cpp
index 97b3884f8cd..e8a80bf2266 100644
--- a/src/mongo/db/commands/plan_cache_commands_test.cpp
+++ b/src/mongo/db/commands/plan_cache_commands_test.cpp
@@ -35,7 +35,6 @@
#include <algorithm>
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/operation_context_noop.h"
#include "mongo/db/query/plan_ranker.h"
#include "mongo/db/query/query_solution.h"
@@ -142,8 +141,7 @@ TEST(PlanCacheCommandsTest, planCacheListQueryShapesOneKey) {
qr->setSort(fromjson("{a: -1}"));
qr->setProj(fromjson("{_id: 0}"));
qr->setCollation(fromjson("{locale: 'mock_reverse_string'}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -174,8 +172,7 @@ TEST(PlanCacheCommandsTest, planCacheClearAllShapes) {
// Create a canonical query
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 1}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -310,14 +307,12 @@ TEST(PlanCacheCommandsTest, planCacheClearOneKey) {
// Create 2 canonical queries.
auto qrA = stdx::make_unique<QueryRequest>(nss);
qrA->setFilter(fromjson("{a: 1}"));
- auto statusWithCQA = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qrA), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQA = CanonicalQuery::canonicalize(opCtx.get(), std::move(qrA));
ASSERT_OK(statusWithCQA.getStatus());
auto qrB = stdx::make_unique<QueryRequest>(nss);
qrB->setFilter(fromjson("{b: 1}"));
unique_ptr<CanonicalQuery> cqA = std::move(statusWithCQA.getValue());
- auto statusWithCQB = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qrB), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQB = CanonicalQuery::canonicalize(opCtx.get(), std::move(qrB));
ASSERT_OK(statusWithCQB.getStatus());
unique_ptr<CanonicalQuery> cqB = std::move(statusWithCQB.getValue());
@@ -365,15 +360,13 @@ TEST(PlanCacheCommandsTest, planCacheClearOneKeyCollation) {
// Create 2 canonical queries, one with collation.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 'foo'}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
auto qrCollation = stdx::make_unique<QueryRequest>(nss);
qrCollation->setFilter(fromjson("{a: 'foo'}"));
qrCollation->setCollation(fromjson("{locale: 'mock_reverse_string'}"));
- auto statusWithCQCollation = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qrCollation), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQCollation = CanonicalQuery::canonicalize(opCtx.get(), std::move(qrCollation));
ASSERT_OK(statusWithCQCollation.getStatus());
unique_ptr<CanonicalQuery> cqCollation = std::move(statusWithCQCollation.getValue());
@@ -519,8 +512,7 @@ TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionTrue) {
// Create a canonical query
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 1}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -547,8 +539,7 @@ TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionFalse) {
// Create a canonical query
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 1}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -578,15 +569,13 @@ TEST(PlanCacheCommandsTest, planCacheListPlansCollation) {
// Create 2 canonical queries, one with collation.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 'foo'}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
auto qrCollation = stdx::make_unique<QueryRequest>(nss);
qrCollation->setFilter(fromjson("{a: 'foo'}"));
qrCollation->setCollation(fromjson("{locale: 'mock_reverse_string'}"));
- auto statusWithCQCollation = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qrCollation), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQCollation = CanonicalQuery::canonicalize(opCtx.get(), std::move(qrCollation));
ASSERT_OK(statusWithCQCollation.getStatus());
unique_ptr<CanonicalQuery> cqCollation = std::move(statusWithCQCollation.getValue());
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 24f5501dba1..bb27f53b049 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -113,7 +113,14 @@ RecordId Helpers::findOne(OperationContext* opCtx,
auto qr = stdx::make_unique<QueryRequest>(collection->ns());
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
massert(17244, "Could not canonicalize " + query.toString(), statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/db/exec/projection.cpp b/src/mongo/db/exec/projection.cpp
index b16dd789915..65ee238c4a0 100644
--- a/src/mongo/db/exec/projection.cpp
+++ b/src/mongo/db/exec/projection.cpp
@@ -61,8 +61,7 @@ ProjectionStage::ProjectionStage(OperationContext* opCtx,
_projObj = params.projObj;
if (ProjectionStageParams::NO_FAST_PATH == _projImpl) {
- _exec.reset(new ProjectionExec(
- params.projObj, params.fullExpression, params.collator, *params.extensionsCallback));
+ _exec.reset(new ProjectionExec(params.projObj, params.fullExpression, params.collator));
} else {
// We shouldn't need the full expression if we're fast-pathing.
invariant(NULL == params.fullExpression);
diff --git a/src/mongo/db/exec/projection.h b/src/mongo/db/exec/projection.h
index a7422eb180f..185c94ff2be 100644
--- a/src/mongo/db/exec/projection.h
+++ b/src/mongo/db/exec/projection.h
@@ -38,7 +38,6 @@
namespace mongo {
class CollatorInterface;
-class ExtensionsCallback;
struct ProjectionStageParams {
enum ProjectionImplementation {
@@ -52,8 +51,6 @@ struct ProjectionStageParams {
SIMPLE_DOC
};
- ProjectionStageParams(const ExtensionsCallback& wc) : extensionsCallback(&wc) {}
-
ProjectionImplementation projImpl = NO_FAST_PATH;
// The projection object. We lack a ProjectionExpression or similar so we use a BSONObj.
@@ -68,9 +65,6 @@ struct ProjectionStageParams {
// from. Otherwise, this field is ignored.
BSONObj coveredKeyObj;
- // Used for creating context for the match extensions processing. Not owned.
- const ExtensionsCallback* extensionsCallback;
-
// The collator this operation should use to compare strings. If null, the collation is a simple
// binary compare.
const CollatorInterface* collator = nullptr;
diff --git a/src/mongo/db/exec/projection_exec.cpp b/src/mongo/db/exec/projection_exec.cpp
index 230673dcc7e..d4842ac1e74 100644
--- a/src/mongo/db/exec/projection_exec.cpp
+++ b/src/mongo/db/exec/projection_exec.cpp
@@ -79,8 +79,7 @@ ProjectionExec::ProjectionExec()
ProjectionExec::ProjectionExec(const BSONObj& spec,
const MatchExpression* queryExpression,
- const CollatorInterface* collator,
- const ExtensionsCallback& extensionsCallback)
+ const CollatorInterface* collator)
: _include(true),
_special(false),
_source(spec),
@@ -133,7 +132,7 @@ ProjectionExec::ProjectionExec(const BSONObj& spec,
verify(elemMatchObj.isOwned());
_elemMatchObjs.push_back(elemMatchObj);
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(elemMatchObj, extensionsCallback, _collator);
+ MatchExpressionParser::parse(elemMatchObj, _collator);
verify(statusWithMatcher.isOK());
// And store it in _matchers.
_matchers[mongoutils::str::before(e.fieldName(), '.').c_str()] =
diff --git a/src/mongo/db/exec/projection_exec.h b/src/mongo/db/exec/projection_exec.h
index b06340e5f12..9575d59042f 100644
--- a/src/mongo/db/exec/projection_exec.h
+++ b/src/mongo/db/exec/projection_exec.h
@@ -68,8 +68,7 @@ public:
ProjectionExec(const BSONObj& spec,
const MatchExpression* queryExpression,
- const CollatorInterface* collator,
- const ExtensionsCallback& extensionsCallback);
+ const CollatorInterface* collator);
~ProjectionExec();
diff --git a/src/mongo/db/exec/projection_exec_test.cpp b/src/mongo/db/exec/projection_exec_test.cpp
index 673ad7c3c48..41c40c2b287 100644
--- a/src/mongo/db/exec/projection_exec_test.cpp
+++ b/src/mongo/db/exec/projection_exec_test.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/exec/working_set_computed_data.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/unittest.h"
#include <memory>
@@ -51,8 +50,7 @@ using std::unique_ptr;
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
ASSERT_TRUE(status.isOK());
return std::move(status.getValue());
}
@@ -85,8 +83,7 @@ void testTransform(const char* specStr,
BSONObj spec = fromjson(specStr);
BSONObj query = fromjson(queryStr);
unique_ptr<MatchExpression> queryExpression = parseMatchExpression(query);
- ProjectionExec exec(
- spec, queryExpression.get(), collator, ExtensionsCallbackDisallowExtensions());
+ ProjectionExec exec(spec, queryExpression.get(), collator);
// Create working set member.
WorkingSetMember wsm;
@@ -169,8 +166,7 @@ BSONObj transformMetaSortKeyCovered(const BSONObj& sortKey,
wsm->addComputed(new SortKeyComputedData(sortKey));
ws.transitionToRecordIdAndIdx(wsid);
- ProjectionExec projExec(
- fromjson(projSpec), nullptr, nullptr, ExtensionsCallbackDisallowExtensions());
+ ProjectionExec projExec(fromjson(projSpec), nullptr, nullptr);
ASSERT_OK(projExec.transform(wsm));
return wsm->obj.value();
@@ -183,7 +179,7 @@ BSONObj transformCovered(BSONObj projSpec, const IndexKeyDatum& ikd) {
wsm->keyData.push_back(ikd);
ws.transitionToRecordIdAndIdx(wsid);
- ProjectionExec projExec(projSpec, nullptr, nullptr, ExtensionsCallbackDisallowExtensions());
+ ProjectionExec projExec(projSpec, nullptr, nullptr);
ASSERT_OK(projExec.transform(wsm));
return wsm->obj.value();
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index dfd382a2aec..d8186f637e0 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -248,8 +248,14 @@ public:
BSONObj argObj = e.Obj();
if (filterTag == e.fieldName()) {
const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx;
StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- argObj, ExtensionsCallbackReal(opCtx, &collection->ns()), collator);
+ argObj,
+ collator,
+ expCtx,
+ ExtensionsCallbackReal(opCtx, &collection->ns()),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithMatcher.isOK()) {
return NULL;
}
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index 672af4c8c75..ca8281aeb6e 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -180,8 +180,6 @@ Status SubplanStage::planSubqueries() {
LOG(5) << "Subplanner: index " << i << " is " << ie;
}
- const ExtensionsCallbackReal extensionsCallback(getOpCtx(), &_collection->ns());
-
for (size_t i = 0; i < _orExpression->numChildren(); ++i) {
// We need a place to shove the results from planning this branch.
_branchResults.push_back(stdx::make_unique<BranchPlanningResult>());
@@ -190,8 +188,7 @@ Status SubplanStage::planSubqueries() {
MatchExpression* orChild = _orExpression->getChild(i);
// Turn the i-th child into its own query.
- auto statusWithCQ =
- CanonicalQuery::canonicalize(getOpCtx(), *_query, orChild, extensionsCallback);
+ auto statusWithCQ = CanonicalQuery::canonicalize(getOpCtx(), *_query, orChild);
if (!statusWithCQ.isOK()) {
mongoutils::str::stream ss;
ss << "Can't canonicalize subchild " << orChild->toString() << " "
diff --git a/src/mongo/db/matcher/SConscript b/src/mongo/db/matcher/SConscript
index e8c9146cf69..8d8b89496bd 100644
--- a/src/mongo/db/matcher/SConscript
+++ b/src/mongo/db/matcher/SConscript
@@ -43,7 +43,6 @@ env.Library(
'expression_where_noop.cpp',
'expression_with_placeholder.cpp',
'extensions_callback.cpp',
- 'extensions_callback_disallow_extensions.cpp',
'extensions_callback_noop.cpp',
'match_details.cpp',
'matchable.cpp',
diff --git a/src/mongo/db/matcher/copyable_match_expression.h b/src/mongo/db/matcher/copyable_match_expression.h
index 9f17fd1b082..8961dce131d 100644
--- a/src/mongo/db/matcher/copyable_match_expression.h
+++ b/src/mongo/db/matcher/copyable_match_expression.h
@@ -29,6 +29,7 @@
#pragma once
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
namespace mongo {
@@ -50,11 +51,15 @@ public:
* encounter an error.
*/
CopyableMatchExpression(BSONObj matchAST,
- std::unique_ptr<const ExtensionsCallback> extensionsCallback,
- const CollatorInterface* collator)
+ const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ std::unique_ptr<const ExtensionsCallback> extensionsCallback =
+ stdx::make_unique<ExtensionsCallbackNoop>(),
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+ MatchExpressionParser::kBanAllSpecialFeatures)
: _matchAST(matchAST), _extensionsCallback(std::move(extensionsCallback)) {
- StatusWithMatchExpression parseResult =
- MatchExpressionParser::parse(_matchAST, *_extensionsCallback, collator);
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(
+ _matchAST, collator, expCtx, *_extensionsCallback, allowedFeatures);
uassertStatusOK(parseResult.getStatus());
_matchExpr = std::move(parseResult.getValue());
}
@@ -67,9 +72,18 @@ public:
* if there other CopyableMatchExpression objects referencing this MatchExpression, they don't
* see the change in collator.
*/
- void setCollator(const CollatorInterface* collator) {
- StatusWithMatchExpression parseResult =
- MatchExpressionParser::parse(_matchAST, *_extensionsCallback, collator);
+ void setCollator(const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr) {
+ // We can allow all features because any features that were allowed in the original
+ // MatchExpression construction should be allowed now.
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+ MatchExpressionParser::kAllowAllSpecialFeatures;
+ if (!expCtx) {
+ allowedFeatures = allowedFeatures & ~MatchExpressionParser::AllowedFeatures::kExpr;
+ }
+
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(
+ _matchAST, collator, expCtx, *_extensionsCallback, allowedFeatures);
invariantOK(parseResult.getStatus());
_matchExpr = std::move(parseResult.getValue());
}
diff --git a/src/mongo/db/matcher/expression_algo_test.cpp b/src/mongo/db/matcher/expression_algo_test.cpp
index c01f77a183b..b97146bc08b 100644
--- a/src/mongo/db/matcher/expression_algo_test.cpp
+++ b/src/mongo/db/matcher/expression_algo_test.cpp
@@ -37,8 +37,6 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_algo.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
-#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/platform/decimal128.h"
@@ -54,8 +52,7 @@ class ParsedMatchExpression {
public:
ParsedMatchExpression(const std::string& str, const CollatorInterface* collator = nullptr)
: _obj(fromjson(str)) {
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(_obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(_obj, collator);
ASSERT_OK(result.getStatus());
_expr = std::move(result.getValue());
}
@@ -74,10 +71,8 @@ TEST(ExpressionAlgoIsSubsetOf, NullAndOmittedField) {
// an Undefined type.
BSONObj undefined = fromjson("{a: undefined}");
const CollatorInterface* collator = nullptr;
- ASSERT_EQUALS(
- ErrorCodes::BadValue,
- MatchExpressionParser::parse(undefined, ExtensionsCallbackDisallowExtensions(), collator)
- .getStatus());
+ ASSERT_EQUALS(ErrorCodes::BadValue,
+ MatchExpressionParser::parse(undefined, collator).getStatus());
ParsedMatchExpression empty("{}");
ParsedMatchExpression null("{a: null}");
@@ -714,8 +709,7 @@ TEST(ExpressionAlgoIsSubsetOf, NonMatchingCollationsNoStringComparison) {
TEST(IsIndependent, AndIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -726,8 +720,7 @@ TEST(IsIndependent, AndIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, ElemMatchIsNotIndependent) {
BSONObj matchPredicate = fromjson("{x: {$elemMatch: {y: 1}}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -739,8 +732,7 @@ TEST(IsIndependent, ElemMatchIsNotIndependent) {
TEST(IsIndependent, NorIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$nor: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -751,8 +743,7 @@ TEST(IsIndependent, NorIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, NotIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -763,8 +754,7 @@ TEST(IsIndependent, NotIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, OrIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$or: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -775,8 +765,7 @@ TEST(IsIndependent, OrIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, AndWithDottedFieldPathsIsNotIndependent) {
BSONObj matchPredicate = fromjson("{$and: [{'a': 1}, {'a.b': 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -787,8 +776,7 @@ TEST(IsIndependent, AndWithDottedFieldPathsIsNotIndependent) {
TEST(IsIndependent, BallIsIndependentOfBalloon) {
BSONObj matchPredicate = fromjson("{'a.ball': 4}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -800,8 +788,7 @@ TEST(IsIndependent, BallIsIndependentOfBalloon) {
TEST(SplitMatchExpression, AndWithSplittableChildrenIsSplittable) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -822,8 +809,7 @@ TEST(SplitMatchExpression, AndWithSplittableChildrenIsSplittable) {
TEST(SplitMatchExpression, NorWithIndependentChildrenIsSplittable) {
BSONObj matchPredicate = fromjson("{$nor: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -844,8 +830,7 @@ TEST(SplitMatchExpression, NorWithIndependentChildrenIsSplittable) {
TEST(SplitMatchExpression, NotWithIndependentChildIsSplittable) {
BSONObj matchPredicate = fromjson("{x: {$not: {$gt: 4}}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -862,8 +847,7 @@ TEST(SplitMatchExpression, NotWithIndependentChildIsSplittable) {
TEST(SplitMatchExpression, OrWithOnlyIndependentChildrenIsNotSplittable) {
BSONObj matchPredicate = fromjson("{$or: [{a: 1}, {b: 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -883,8 +867,7 @@ TEST(SplitMatchExpression, ComplexMatchExpressionSplitsCorrectly) {
"{$or: [{'a.b' : 3}, {'a.b.c': 4}]},"
"{$nor: [{x: {$gt: 4}}, {$and: [{x: {$not: {$eq: 1}}}, {y: 3}]}]}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -909,8 +892,7 @@ TEST(SplitMatchExpression, ComplexMatchExpressionSplitsCorrectly) {
TEST(SplitMatchExpression, ShouldNotExtractPrefixOfDottedPathAsIndependent) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {'a.b': 1}, {'a.c': 1}]}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -931,7 +913,7 @@ TEST(SplitMatchExpression, ShouldNotExtractPrefixOfDottedPathAsIndependent) {
TEST(SplitMatchExpression, ShouldMoveIndependentLeafPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{a: 1}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "b"}};
@@ -949,7 +931,7 @@ TEST(SplitMatchExpression, ShouldMoveIndependentLeafPredicateAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveIndependentAndPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 2}]}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -967,7 +949,7 @@ TEST(SplitMatchExpression, ShouldMoveIndependentAndPredicateAcrossRename) {
TEST(SplitMatchExpression, ShouldSplitPartiallyDependentAndPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 2}]}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -988,7 +970,7 @@ TEST(SplitMatchExpression, ShouldSplitPartiallyDependentAndPredicateAcrossRename
TEST(SplitMatchExpression, ShouldSplitPartiallyDependentComplexPredicateMultipleRenames) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {$or: [{b: 2}, {c: 3}]}]}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"b", "d"}, {"c", "e"}};
@@ -1010,7 +992,7 @@ TEST(SplitMatchExpression,
ShouldSplitPartiallyDependentComplexPredicateMultipleRenamesDottedPaths) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {$or: [{'d.e.f': 2}, {'e.f.g': 3}]}]}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"d.e.f", "x"}, {"e.f.g", "y"}};
@@ -1031,7 +1013,7 @@ TEST(SplitMatchExpression,
TEST(SplitMatchExpression, ShouldNotMoveElemMatchObjectAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {b: 3}}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1049,7 +1031,7 @@ TEST(SplitMatchExpression, ShouldNotMoveElemMatchObjectAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveElemMatchValueAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {$eq: 3}}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1067,7 +1049,7 @@ TEST(SplitMatchExpression, ShouldNotMoveElemMatchValueAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveTypeAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$type: 16}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1085,7 +1067,7 @@ TEST(SplitMatchExpression, ShouldMoveTypeAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveSizeAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$size: 3}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1103,7 +1085,7 @@ TEST(SplitMatchExpression, ShouldNotMoveSizeAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveMinItemsAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMinItems: 3}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1121,7 +1103,7 @@ TEST(SplitMatchExpression, ShouldNotMoveMinItemsAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveMaxItemsAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMaxItems: 3}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1139,7 +1121,7 @@ TEST(SplitMatchExpression, ShouldNotMoveMaxItemsAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveMinLengthAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMinLength: 3}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1157,7 +1139,7 @@ TEST(SplitMatchExpression, ShouldMoveMinLengthAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveMaxLengthAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMaxLength: 3}}");
const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1175,8 +1157,7 @@ TEST(SplitMatchExpression, ShouldMoveMaxLengthAcrossRename) {
TEST(MapOverMatchExpression, DoesMapOverLogicalNodes) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
const CollatorInterface* collator = nullptr;
- auto swMatchExpression =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(swMatchExpression.getStatus());
bool hasLogicalNode = false;
@@ -1194,8 +1175,7 @@ TEST(MapOverMatchExpression, DoesMapOverLogicalNodes) {
TEST(MapOverMatchExpression, DoesMapOverLeafNodes) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
const CollatorInterface* collator = nullptr;
- auto swMatchExpression =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(swMatchExpression.getStatus());
bool hasLeafNode = false;
@@ -1213,8 +1193,7 @@ TEST(MapOverMatchExpression, DoesMapOverLeafNodes) {
TEST(MapOverMatchExpression, DoesPassPath) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {b: 1}}}");
const CollatorInterface* collator = nullptr;
- auto swMatchExpression =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(swMatchExpression.getStatus());
std::vector<std::string> paths;
@@ -1232,8 +1211,7 @@ TEST(MapOverMatchExpression, DoesPassPath) {
TEST(MapOverMatchExpression, DoesMapOverNodesWithMultipleChildren) {
BSONObj matchPredicate = fromjson("{$and: [{a: {$gt: 1}}, {b: {$lte: 2}}]}");
const CollatorInterface* collator = nullptr;
- auto swMatchExpression =
- MatchExpressionParser::parse(matchPredicate, ExtensionsCallbackNoop(), collator);
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(swMatchExpression.getStatus());
size_t nodeCount = 0;
diff --git a/src/mongo/db/matcher/expression_geo_test.cpp b/src/mongo/db/matcher/expression_geo_test.cpp
index 52ed8ac77e1..de7bd773c8a 100644
--- a/src/mongo/db/matcher/expression_geo_test.cpp
+++ b/src/mongo/db/matcher/expression_geo_test.cpp
@@ -36,7 +36,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_geo.h"
-#include "mongo/db/matcher/matcher.h"
#include "mongo/stdx/memory.h"
namespace mongo {
diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp
index 051e6a6884c..c49382699db 100644
--- a/src/mongo/db/matcher/expression_parser.cpp
+++ b/src/mongo/db/matcher/expression_parser.cpp
@@ -102,7 +102,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison(
ComparisonMatchExpression* cmp,
const BSONElement& e,
const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures) {
std::unique_ptr<ComparisonMatchExpression> temp(cmp);
// Non-equality comparison match expressions cannot have
@@ -114,8 +115,11 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison(
}
if (_isAggExpression(e, expCtx)) {
- auto expr = _parseAggExpression(e, expCtx);
- auto s = temp->init(name, expr);
+ auto expr = _parseAggExpression(e, expCtx, allowedFeatures);
+ if (!expr.isOK()) {
+ return expr.getStatus();
+ }
+ auto s = temp->init(name, expr.getValue());
if (!s.isOK()) {
return s;
}
@@ -138,12 +142,14 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
if (mongoutils::str::equals("$eq", e.fieldName()))
- return _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
if (mongoutils::str::equals("$not", e.fieldName())) {
- return _parseNot(name, e, collator, expCtx, topLevel);
+ return _parseNot(name, e, collator, expCtx, allowedFeatures, topLevel);
}
auto parseExpMatchType = MatchExpressionParser::parsePathAcceptingKeyword(e);
@@ -159,21 +165,25 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
switch (*parseExpMatchType) {
case PathAcceptingKeyword::LESS_THAN:
- return _parseComparison(name, new LTMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new LTMatchExpression(), e, collator, expCtx, allowedFeatures);
case PathAcceptingKeyword::LESS_THAN_OR_EQUAL:
- return _parseComparison(name, new LTEMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new LTEMatchExpression(), e, collator, expCtx, allowedFeatures);
case PathAcceptingKeyword::GREATER_THAN:
- return _parseComparison(name, new GTMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new GTMatchExpression(), e, collator, expCtx, allowedFeatures);
case PathAcceptingKeyword::GREATER_THAN_OR_EQUAL:
- return _parseComparison(name, new GTEMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new GTEMatchExpression(), e, collator, expCtx, allowedFeatures);
case PathAcceptingKeyword::NOT_EQUAL: {
if (RegEx == e.type()) {
// Just because $ne can be rewritten as the negation of an
// equality does not mean that $ne of a regex is allowed. See SERVER-1705.
return {Status(ErrorCodes::BadValue, "Can't have regex as arg to $ne.")};
}
- StatusWithMatchExpression s =
- _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx);
+ StatusWithMatchExpression s = _parseComparison(
+ name, new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
if (!s.isOK())
return s;
std::unique_ptr<NotMatchExpression> n = stdx::make_unique<NotMatchExpression>();
@@ -183,7 +193,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
return {std::move(n)};
}
case PathAcceptingKeyword::EQUALITY:
- return _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx);
+ return _parseComparison(
+ name, new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
case PathAcceptingKeyword::IN_EXPR: {
if (e.type() != Array)
@@ -291,14 +302,14 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
}
case PathAcceptingKeyword::ELEM_MATCH:
- return _parseElemMatch(name, e, collator, expCtx, topLevel);
+ return _parseElemMatch(name, e, collator, expCtx, allowedFeatures, topLevel);
case PathAcceptingKeyword::ALL:
- return _parseAll(name, e, collator, expCtx, topLevel);
+ return _parseAll(name, e, collator, expCtx, allowedFeatures, topLevel);
case PathAcceptingKeyword::WITHIN:
case PathAcceptingKeyword::GEO_INTERSECTS:
- return _parseGeo(name, *parseExpMatchType, context);
+ return _parseGeo(name, *parseExpMatchType, context, allowedFeatures);
case PathAcceptingKeyword::GEO_NEAR:
return {Status(ErrorCodes::BadValue,
@@ -341,7 +352,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
str::stream() << "$_internalSchemaObjectMatch must be an object");
}
- auto parsedSubObjExpr = _parse(e.Obj(), collator, expCtx, topLevel);
+ auto parsedSubObjExpr = _parse(e.Obj(), collator, expCtx, allowedFeatures, topLevel);
if (!parsedSubObjExpr.isOK()) {
return parsedSubObjExpr;
}
@@ -427,7 +438,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
<< "must be an object");
}
StatusWithMatchExpression query =
- _parse(second.embeddedObject(), collator, expCtx, topLevel);
+ _parse(second.embeddedObject(), collator, expCtx, allowedFeatures, topLevel);
if (!query.isOK()) {
return query.getStatus();
}
@@ -452,6 +463,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
const BSONObj& obj,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
std::unique_ptr<AndMatchExpression> root = stdx::make_unique<AndMatchExpression>();
@@ -466,7 +478,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
if (e.type() != Array)
return {Status(ErrorCodes::BadValue, "$or must be an array")};
std::unique_ptr<OrMatchExpression> temp = stdx::make_unique<OrMatchExpression>();
- Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel);
+ Status s = _parseTreeList(
+ e.Obj(), temp.get(), collator, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -474,7 +487,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
if (e.type() != Array)
return {Status(ErrorCodes::BadValue, "$and must be an array")};
std::unique_ptr<AndMatchExpression> temp = stdx::make_unique<AndMatchExpression>();
- Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel);
+ Status s = _parseTreeList(
+ e.Obj(), temp.get(), collator, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -482,7 +496,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
if (e.type() != Array)
return {Status(ErrorCodes::BadValue, "$nor must be an array")};
std::unique_ptr<NorMatchExpression> temp = stdx::make_unique<NorMatchExpression>();
- Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel);
+ Status s = _parseTreeList(
+ e.Obj(), temp.get(), collator, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -494,11 +509,19 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
// Don't do anything with the expression; CanonicalQuery::init() will look through
// the BSONObj again for a $atomic/$isolated.
} else if (mongoutils::str::equals("where", rest)) {
+ if ((allowedFeatures & AllowedFeatures::kJavascript) == 0u) {
+ return {Status(ErrorCodes::BadValue, "$where is not allowed in this context")};
+ }
+
StatusWithMatchExpression s = _extensionsCallback->parseWhere(e);
if (!s.isOK())
return s;
root->add(s.getValue().release());
} else if (mongoutils::str::equals("text", rest)) {
+ if ((allowedFeatures & AllowedFeatures::kText) == 0u) {
+ return {Status(ErrorCodes::BadValue, "$text is not allowed in this context")};
+ }
+
StatusWithMatchExpression s = _extensionsCallback->parseText(e);
if (!s.isOK()) {
return s;
@@ -526,7 +549,11 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
} else if (mongoutils::str::equals("_internalSchemaCond", rest)) {
auto condExpr =
_parseInternalSchemaFixedArityArgument<InternalSchemaCondMatchExpression>(
- InternalSchemaCondMatchExpression::kName, e, collator, expCtx);
+ InternalSchemaCondMatchExpression::kName,
+ e,
+ collator,
+ expCtx,
+ allowedFeatures);
if (!condExpr.isOK()) {
return condExpr.getStatus();
}
@@ -537,8 +564,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
return {
Status(ErrorCodes::TypeMismatch, "$_internalSchemaXor must be an array")};
auto xorExpr = stdx::make_unique<InternalSchemaXorMatchExpression>();
- Status s =
- _parseTreeList(e.Obj(), xorExpr.get(), collator, expCtx, childIsTopLevel);
+ Status s = _parseTreeList(
+ e.Obj(), xorExpr.get(), collator, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(xorExpr.release());
@@ -587,8 +614,13 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
}
if (_isExpressionDocument(e, false, expCtx)) {
- Status s =
- _parseSub(e.fieldName(), e.Obj(), root.get(), collator, expCtx, childIsTopLevel);
+ Status s = _parseSub(e.fieldName(),
+ e.Obj(),
+ root.get(),
+ collator,
+ expCtx,
+ allowedFeatures,
+ childIsTopLevel);
if (!s.isOK())
return s;
continue;
@@ -602,8 +634,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
continue;
}
- auto eq =
- _parseComparison(e.fieldName(), new EqualityMatchExpression(), e, collator, expCtx);
+ auto eq = _parseComparison(
+ e.fieldName(), new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
if (!eq.isOK())
return eq;
@@ -624,6 +656,7 @@ Status MatchExpressionParser::_parseSub(const char* name,
AndMatchExpression* root,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
// The one exception to {field : {fully contained argument} } is, of course, geo. Example:
// sub == { field : {$near[Sphere]: [0,0], $maxDistance: 1000, $minDistance: 10 } }
@@ -638,17 +671,10 @@ Status MatchExpressionParser::_parseSub(const char* name,
if (geoIt.more()) {
BSONElement firstElt = geoIt.next();
if (firstElt.isABSONObj()) {
- const char* fieldName = firstElt.fieldName();
- // TODO: Having these $fields here isn't ideal but we don't want to pull in anything
- // from db/geo at this point, since it may not actually be linked in...
- if (mongoutils::str::equals(fieldName, "$near") ||
- mongoutils::str::equals(fieldName, "$nearSphere") ||
- mongoutils::str::equals(fieldName, "$geoNear")) {
+ if (MatchExpressionParser::parsePathAcceptingKeyword(firstElt) ==
+ PathAcceptingKeyword::GEO_NEAR) {
StatusWithMatchExpression s =
- _parseGeo(name,
- *MatchExpressionParser::parsePathAcceptingKeyword(
- firstElt, PathAcceptingKeyword::EQUALITY),
- sub);
+ _parseGeo(name, PathAcceptingKeyword::GEO_NEAR, sub, allowedFeatures);
if (s.isOK()) {
root->add(s.getValue().release());
}
@@ -664,8 +690,8 @@ Status MatchExpressionParser::_parseSub(const char* name,
BSONElement deep = j.next();
const bool childIsTopLevel = false;
- StatusWithMatchExpression s =
- _parseSubField(sub, root, name, deep, collator, expCtx, childIsTopLevel);
+ StatusWithMatchExpression s = _parseSubField(
+ sub, root, name, deep, collator, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s.getStatus();
@@ -885,6 +911,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
if (e.type() != Object)
return {Status(ErrorCodes::BadValue, "$elemMatch needs an Object")};
@@ -919,7 +946,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
// value case
AndMatchExpression theAnd;
- Status s = _parseSub("", obj, &theAnd, collator, expCtx, topLevel);
+ Status s = _parseSub("", obj, &theAnd, collator, expCtx, allowedFeatures, topLevel);
if (!s.isOK())
return s;
@@ -943,7 +970,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
// object case
- StatusWithMatchExpression subRaw = _parse(obj, collator, expCtx, topLevel);
+ StatusWithMatchExpression subRaw = _parse(obj, collator, expCtx, allowedFeatures, topLevel);
if (!subRaw.isOK())
return subRaw;
std::unique_ptr<MatchExpression> sub = std::move(subRaw.getValue());
@@ -968,6 +995,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
if (e.type() != Array)
return {Status(ErrorCodes::BadValue, "$all needs an array")};
@@ -997,8 +1025,12 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(
}
const bool childIsTopLevel = false;
- StatusWithMatchExpression inner = _parseElemMatch(
- name, hopefullyElemMatchObj.firstElement(), collator, expCtx, childIsTopLevel);
+ StatusWithMatchExpression inner = _parseElemMatch(name,
+ hopefullyElemMatchObj.firstElement(),
+ collator,
+ expCtx,
+ allowedFeatures,
+ childIsTopLevel);
if (!inner.isOK())
return inner;
myAnd->add(inner.getValue().release());
@@ -1249,7 +1281,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityA
StringData name,
const BSONElement& input,
const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures) {
constexpr auto arity = T::arity();
if (input.type() != BSONType::Array) {
return {ErrorCodes::FailedToParse,
@@ -1278,7 +1311,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityA
}
const bool isTopLevel = false;
- auto subexpr = _parse(elem.embeddedObject(), collator, expCtx, isTopLevel);
+ auto subexpr = _parse(elem.embeddedObject(), collator, expCtx, allowedFeatures, isTopLevel);
if (!subexpr.isOK()) {
return subexpr.getStatus();
}
@@ -1586,7 +1619,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaAllowedProp
StatusWithMatchExpression MatchExpressionParser::_parseGeo(const char* name,
PathAcceptingKeyword type,
- const BSONObj& section) {
+ const BSONObj& section,
+ AllowedFeatureSet allowedFeatures) {
if (PathAcceptingKeyword::WITHIN == type || PathAcceptingKeyword::GEO_INTERSECTS == type) {
std::unique_ptr<GeoExpression> gq = stdx::make_unique<GeoExpression>(name);
Status parseStatus = gq->parseFrom(section);
@@ -1602,6 +1636,12 @@ StatusWithMatchExpression MatchExpressionParser::_parseGeo(const char* name,
return {std::move(e)};
} else {
invariant(PathAcceptingKeyword::GEO_NEAR == type);
+
+ if ((allowedFeatures & AllowedFeatures::kGeoNear) == 0u) {
+ return {Status(ErrorCodes::BadValue,
+ "$geoNear, $near, and $nearSphere are not allowed in this context")};
+ }
+
std::unique_ptr<GeoNearExpression> nq = stdx::make_unique<GeoNearExpression>(name);
Status s = nq->parseFrom(section);
if (!s.isOK()) {
@@ -1633,10 +1673,16 @@ bool MatchExpressionParser::_isAggExpression(
return obj.firstElementFieldName() == kAggExpression;
}
-boost::intrusive_ptr<Expression> MatchExpressionParser::_parseAggExpression(
- BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+StatusWith<boost::intrusive_ptr<Expression>> MatchExpressionParser::_parseAggExpression(
+ BSONElement elem,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures) {
invariant(expCtx);
+ if ((allowedFeatures & AllowedFeatures::kExpr) == 0u) {
+ return {Status(ErrorCodes::BadValue, "$expr is not allowed in this context")};
+ }
+
auto expr = Expression::parseOperand(
expCtx, elem.embeddedObject().firstElement(), expCtx->variablesParseState);
return expr->optimize();
diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h
index 621a35e4451..75ed1a60dd7 100644
--- a/src/mongo/db/matcher/expression_parser.h
+++ b/src/mongo/db/matcher/expression_parser.h
@@ -37,6 +37,7 @@
#include "mongo/db/matcher/expression_tree.h"
#include "mongo/db/matcher/expression_type.h"
#include "mongo/db/matcher/extensions_callback.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/expression_context.h"
#include "mongo/stdx/functional.h"
@@ -84,6 +85,20 @@ enum class PathAcceptingKeyword {
class MatchExpressionParser {
public:
/**
+ * Features allowed in match expression parsing.
+ */
+ enum AllowedFeatures {
+ kText = 1,
+ kGeoNear = 1 << 1,
+ kJavascript = 1 << 2,
+ kExpr = 1 << 3,
+ };
+ using AllowedFeatureSet = unsigned long long;
+ static constexpr AllowedFeatureSet kBanAllSpecialFeatures = 0;
+ static constexpr AllowedFeatureSet kAllowAllSpecialFeatures =
+ std::numeric_limits<unsigned long long>::max();
+
+ /**
* Constant double representation of 2^63.
*/
static const double kLongLongMaxPlusOneAsDouble;
@@ -104,12 +119,18 @@ public:
*/
static StatusWithMatchExpression parse(
const BSONObj& obj,
- const ExtensionsCallback& extensionsCallback,
const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr) {
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
+ AllowedFeatureSet allowedFeatures = kBanAllSpecialFeatures) {
+ // A non-null ExpressionContext is required for parsing $expr.
+ if (!expCtx) {
+ invariant((allowedFeatures & AllowedFeatures::kExpr) == 0u);
+ }
+
const bool topLevelCall = true;
return MatchExpressionParser(&extensionsCallback)
- ._parse(obj, collator, expCtx, topLevelCall);
+ ._parse(obj, collator, expCtx, allowedFeatures, topLevelCall);
}
/**
@@ -171,6 +192,7 @@ private:
StatusWithMatchExpression _parse(const BSONObj& obj,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
/**
@@ -183,6 +205,7 @@ private:
AndMatchExpression* root,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
/**
@@ -196,6 +219,7 @@ private:
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
StatusWithMatchExpression _parseComparison(
@@ -203,7 +227,8 @@ private:
ComparisonMatchExpression* cmp,
const BSONElement& e,
const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx);
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures);
StatusWithMatchExpression _parseMOD(const char* name,
const BSONElement& e,
@@ -231,7 +256,8 @@ private:
StatusWithMatchExpression _parseGeo(const char* name,
PathAcceptingKeyword type,
- const BSONObj& section);
+ const BSONObj& section,
+ AllowedFeatureSet allowedFeatures);
// arrays
@@ -239,12 +265,14 @@ private:
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
StatusWithMatchExpression _parseAll(const char* name,
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
// tree
@@ -253,12 +281,14 @@ private:
ListOfMatchExpression* out,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
StatusWithMatchExpression _parseNot(const char* name,
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel);
/**
@@ -284,7 +314,8 @@ private:
StringData name,
const BSONElement& elem,
const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx);
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures);
/**
* Parses the given BSONElement into a single integer argument and creates a MatchExpression
@@ -310,8 +341,10 @@ private:
bool _isAggExpression(BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx);
- boost::intrusive_ptr<Expression> _parseAggExpression(
- BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx);
+ StatusWith<boost::intrusive_ptr<Expression>> _parseAggExpression(
+ BSONElement elem,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures);
StatusWithMatchExpression _parseInternalSchemaAllowedProperties(
const BSONElement& elem, const CollatorInterface* collator);
diff --git a/src/mongo/db/matcher/expression_parser_array_test.cpp b/src/mongo/db/matcher/expression_parser_array_test.cpp
index 2a9d0467ce3..23cef6b1180 100644
--- a/src/mongo/db/matcher/expression_parser_array_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_array_test.cpp
@@ -38,7 +38,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_array.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
namespace mongo {
@@ -48,8 +47,7 @@ using std::string;
TEST(MatchExpressionParserArrayTest, Size1) {
BSONObj query = BSON("x" << BSON("$size" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -61,8 +59,7 @@ TEST(MatchExpressionParserArrayTest, Size1) {
TEST(MatchExpressionParserArrayTest, SizeAsLong) {
BSONObj query = BSON("x" << BSON("$size" << 2LL));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -74,16 +71,14 @@ TEST(MatchExpressionParserArrayTest, SizeAsLong) {
TEST(MatchExpressionParserArrayTest, SizeAsNegativeLong) {
BSONObj query = BSON("x" << BSON("$size" << -2LL));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeTooLarge) {
BSONObj query = BSON("x" << BSON("$size" << std::numeric_limits<long long>::max()));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -91,16 +86,14 @@ TEST(MatchExpressionParserArrayTest, SizeAsString) {
BSONObj query = BSON("x" << BSON("$size"
<< "a"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithIntegralDouble) {
BSONObj query = BSON("x" << BSON("$size" << 2.0));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -112,32 +105,28 @@ TEST(MatchExpressionParserArrayTest, SizeWithIntegralDouble) {
TEST(MatchExpressionParserArrayTest, SizeWithNegativeIntegralDouble) {
BSONObj query = BSON("x" << BSON("$size" << -2.0));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithDouble) {
BSONObj query = BSON("x" << BSON("$size" << 2.5));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithNegative) {
BSONObj query = BSON("x" << BSON("$size" << -2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeBad) {
BSONObj query = BSON("x" << BSON("$size" << BSONNULL));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -146,8 +135,7 @@ TEST(MatchExpressionParserArrayTest, SizeBad) {
TEST(MatchExpressionParserArrayTest, ElemMatchArr1) {
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("x" << 1 << "y" << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -160,8 +148,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchAnd) {
BSONObj query =
BSON("x" << BSON("$elemMatch" << BSON("$and" << BSON_ARRAY(BSON("x" << 1 << "y" << 2)))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -173,8 +160,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchAnd) {
TEST(MatchExpressionParserArrayTest, ElemMatchNor) {
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("$nor" << BSON_ARRAY(BSON("x" << 1)))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -187,8 +173,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchOr) {
BSONObj query =
BSON("x" << BSON("$elemMatch" << BSON("$or" << BSON_ARRAY(BSON("x" << 1 << "y" << 2)))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -200,8 +185,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchOr) {
TEST(MatchExpressionParserArrayTest, ElemMatchVal1) {
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("$gt" << 5)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -228,8 +212,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef1) {
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("$eq" << match)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -255,8 +238,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef2) {
BSONObj query = BSON("x" << BSON("$elemMatch" << match));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -283,8 +265,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef3) {
BSONObj query = BSON("x" << BSON("$elemMatch" << match));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -327,8 +308,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef4) {
BSONObj query = BSON("x" << BSON("$elemMatch" << matchOutOfOrder));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -358,8 +338,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef5) {
BSONObj query = BSON("x" << BSON("$elemMatch" << matchOutOfOrder));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -399,8 +378,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef6) {
BSONObj query = BSON("x" << BSON("$elemMatch" << matchMissingID));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -438,8 +416,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef7) {
BSONObj query = BSON("x" << BSON("$elemMatch" << matchMissingRef));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -483,8 +460,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef8) {
BSONObj query = BSON("x" << BSON("$elemMatch" << matchDBOnly));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -507,8 +483,7 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef8) {
TEST(MatchExpressionParserArrayTest, All1) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(1 << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -525,8 +500,7 @@ TEST(MatchExpressionParserArrayTest, All1) {
TEST(MatchExpressionParserArrayTest, AllNull) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(BSONNULL)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -541,8 +515,7 @@ TEST(MatchExpressionParserArrayTest, AllNull) {
TEST(MatchExpressionParserArrayTest, AllBadArg) {
BSONObj query = BSON("x" << BSON("$all" << 1));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -556,8 +529,7 @@ TEST(MatchExpressionParserArrayTest, AllBadRegexArg) {
BSONObj query = BSON("x" << operand.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -571,8 +543,7 @@ TEST(MatchExpressionParserArrayTest, AllRegex1) {
BSONObj query = BSON("a" << all.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -599,8 +570,7 @@ TEST(MatchExpressionParserArrayTest, AllRegex2) {
BSONObj query = BSON("a" << all.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -618,8 +588,7 @@ TEST(MatchExpressionParserArrayTest, AllRegex2) {
TEST(MatchExpressionParserArrayTest, AllNonArray) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(5)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -636,8 +605,7 @@ TEST(MatchExpressionParserArrayTest, AllElemMatch1) {
BSONObj internal = BSON("x" << 1 << "y" << 2);
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(BSON("$elemMatch" << internal))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to an AND with a single ELEM_MATCH_OBJECT child.
@@ -658,8 +626,7 @@ TEST(MatchExpressionParserArrayTest, AllElemMatch2) {
BSONObj internal = BSON("z" << 1);
BSONObj query = BSON("x.y" << BSON("$all" << BSON_ARRAY(BSON("$elemMatch" << internal))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to an AND with a single ELEM_MATCH_OBJECT child.
@@ -695,8 +662,7 @@ TEST(MatchExpressionParserArrayTest, AllElemMatch2) {
TEST(MatchExpressionParserArrayTest, AllElemMatch3) {
BSONObj query = fromjson("{x: {$all: [{$elemMatch: {y: 1, z: 1}}]}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
std::unique_ptr<MatchExpression> expr = std::move(result.getValue());
@@ -732,12 +698,11 @@ TEST(MatchExpressionParserArrayTest, AllElemMatchBad) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(BSON("$elemMatch" << internal) << 5)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$all" << BSON_ARRAY(5 << BSON("$elemMatch" << internal))));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -746,26 +711,22 @@ TEST(MatchExpressionParserArrayTest, AllElemMatchBadMixed) {
// $elemMatch first, equality second.
BSONObj bad1 = fromjson("{x: {$all: [{$elemMatch: {y: 1}}, 3]}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result1 =
- MatchExpressionParser::parse(bad1, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result1 = MatchExpressionParser::parse(bad1, collator);
ASSERT_FALSE(result1.isOK());
// equality first, $elemMatch second
BSONObj bad2 = fromjson("{x: {$all: [3, {$elemMatch: {y: 1}}]}}");
- StatusWithMatchExpression result2 =
- MatchExpressionParser::parse(bad2, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result2 = MatchExpressionParser::parse(bad2, collator);
ASSERT_FALSE(result1.isOK());
// $elemMatch first, object second
BSONObj bad3 = fromjson("{x: {$all: [{$elemMatch: {y: 1}}, {z: 1}]}}");
- StatusWithMatchExpression result3 =
- MatchExpressionParser::parse(bad3, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result3 = MatchExpressionParser::parse(bad3, collator);
ASSERT_FALSE(result3.isOK());
// object first, $elemMatch second
BSONObj bad4 = fromjson("{x: {$all: [{z: 1}, {$elemMatch: {y: 1}}]}}");
- StatusWithMatchExpression result4 =
- MatchExpressionParser::parse(bad4, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result4 = MatchExpressionParser::parse(bad4, collator);
ASSERT_FALSE(result4.isOK());
}
@@ -773,8 +734,7 @@ TEST(MatchExpressionParserArrayTest, AllElemMatchBadMixed) {
TEST(MatchExpressionParserArrayTest, AllEmptyString) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -799,8 +759,7 @@ TEST(MatchExpressionParserArrayTest, AllISODate) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(match)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << notMatch)));
@@ -816,8 +775,7 @@ TEST(MatchExpressionParserArrayTest, AllISODate) {
TEST(MatchExpressionParserArrayTest, AllDottedEmptyString) {
BSONObj query = BSON("x.1" << BSON("$all" << BSON_ARRAY("")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -844,8 +802,7 @@ TEST(MatchExpressionParserArrayTest, AllDottedISODate) {
BSONObj query = BSON("x.1" << BSON("$all" << BSON_ARRAY(match)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << notMatch)));
@@ -862,8 +819,7 @@ TEST(MatchExpressionParserArrayTest, AllDottedISODate) {
TEST(MatchExpressionParserArrayTest, AllStringNullCollation) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("string")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::AND, result.getValue()->matchType());
ASSERT_EQUALS(1U, result.getValue()->numChildren());
@@ -876,8 +832,7 @@ TEST(MatchExpressionParserArrayTest, AllStringNullCollation) {
TEST(MatchExpressionParserArrayTest, AllStringCollation) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::AND, result.getValue()->matchType());
ASSERT_EQUALS(1U, result.getValue()->numChildren());
diff --git a/src/mongo/db/matcher/expression_parser_geo_test.cpp b/src/mongo/db/matcher/expression_parser_geo_test.cpp
index c7e82af29ab..b8a17a3ae2f 100644
--- a/src/mongo/db/matcher/expression_parser_geo_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_geo_test.cpp
@@ -34,7 +34,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_geo.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/aggregation_context_fixture.h"
namespace mongo {
@@ -43,8 +43,13 @@ TEST(MatchExpressionParserGeo, WithinBox) {
BSONObj query = fromjson("{a:{$within:{$box:[{x: 4, y:4},[6,6]]}}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(fromjson("{a: [3,4]}")));
@@ -63,7 +68,11 @@ TEST(MatchExpressionParserGeo, RejectsExprAsGeometry) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_NOT_OK(result.getStatus());
}
@@ -73,8 +82,13 @@ TEST(MatchExpressionParserGeoNear, ParseNear) {
"$geometry:{type:\"Point\", coordinates:[0,0]}}}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -91,10 +105,14 @@ TEST(MatchExpressionParserGeoNear, ParseNearExtraField) {
"$geometry:{type:\"Point\", coordinates:[0,0]}}, foo: 1}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
// For $near, $nearSphere, and $geoNear syntax of:
@@ -107,8 +125,13 @@ TEST(MatchExpressionParserGeoNear, ParseValidNear) {
BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: 100, $minDistance: 50}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -123,69 +146,110 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $near: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $near: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $minDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $eq: 40}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$eq: 40, $near: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson(
"{loc: {$near: [0,0], $geoWithin: {$geometry: {type: \"Polygon\", coordinates: []}}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$near: {$foo: 1}}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$minDistance: 10}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
}
@@ -194,8 +258,13 @@ TEST(MatchExpressionParserGeoNear, ParseValidGeoNear) {
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $maxDistance: 100, $minDistance: 50}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -210,40 +279,62 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $geoNear: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $geoNear: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $eq: 1}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $maxDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $minDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
}
@@ -251,8 +342,13 @@ TEST(MatchExpressionParserGeoNear, ParseValidNearSphere) {
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $maxDistance: 100, $minDistance: 50}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -267,40 +363,62 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $nearSphere: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $nearSphere: [0,0]}}");
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_FALSE(result.isOK());
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $maxDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $minDistance: {}}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $eq: 1}}");
const CollatorInterface* collator = nullptr;
- ASSERT_THROWS(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
- .status_with_transitional_ignore(),
- AssertionException);
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_THROWS(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures)
+ .status_with_transitional_ignore(),
+ AssertionException);
}
}
diff --git a/src/mongo/db/matcher/expression_parser_leaf_test.cpp b/src/mongo/db/matcher/expression_parser_leaf_test.cpp
index 7181c8dea59..17c6efc8b4f 100644
--- a/src/mongo/db/matcher/expression_parser_leaf_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_leaf_test.cpp
@@ -33,10 +33,11 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/platform/decimal128.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -48,8 +49,7 @@ TEST(MatchExpressionParserLeafTest, NullCollation) {
BSONObj query = BSON("x"
<< "string");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -61,8 +61,7 @@ TEST(MatchExpressionParserLeafTest, Collation) {
BSONObj query = BSON("x"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -79,8 +78,11 @@ TEST(MatchExpressionParserLeafTest, ConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
@@ -101,21 +103,30 @@ TEST(MatchExpressionParserLeafTest, ConstantExprFailsWithMissingVariable) {
BSONObj query = BSON("x" << BSON("$expr"
<< "$$userVar"));
- ASSERT_THROWS_CODE(auto sw = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx),
- AssertionException,
- 17276);
+ ASSERT_THROWS_CODE(
+ auto sw = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr),
+ AssertionException,
+ 17276);
}
-TEST(MatchExpressionParserLeafTest, ConstantExprFailsWithMissingExpressionContext) {
+DEATH_TEST(MatchExpressionParserLeafTest,
+ ConstantExprFailsWithMissingExpressionContext,
+ "Invariant failure (allowedFeatures & AllowedFeatures::kExpr) == 0u") {
boost::intrusive_ptr<ExpressionContextForTest> nullExpCtx;
const CollatorInterface* collator = nullptr;
BSONObj query = BSON("x" << BSON("$expr"
<< "$$userVar"));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, nullExpCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ nullExpCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
}
@@ -123,8 +134,7 @@ TEST(MatchExpressionParserLeafTest, ConstantExprFailsWithMissingExpressionContex
TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
BSONObj query = BSON("x" << BSON("$eq" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -135,8 +145,7 @@ TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
TEST(MatchExpressionParserLeafTest, SimpleEQUndefined) {
BSONObj query = BSON("x" << BSON("$eq" << BSONUndefined));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -144,8 +153,7 @@ TEST(MatchExpressionParserLeafTest, EQNullCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -157,8 +165,7 @@ TEST(MatchExpressionParserLeafTest, EQCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -175,8 +182,11 @@ TEST(MatchExpressionParserLeafTest, EQConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
@@ -193,8 +203,7 @@ TEST(MatchExpressionParserLeafTest, EQConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleGT1) {
BSONObj query = BSON("x" << BSON("$gt" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -205,8 +214,7 @@ TEST(MatchExpressionParserLeafTest, GTNullCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get());
@@ -218,8 +226,7 @@ TEST(MatchExpressionParserLeafTest, GTCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get());
@@ -236,8 +243,11 @@ TEST(MatchExpressionParserLeafTest, GTConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
@@ -254,8 +264,7 @@ TEST(MatchExpressionParserLeafTest, GTConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleLT1) {
BSONObj query = BSON("x" << BSON("$lt" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -267,8 +276,7 @@ TEST(MatchExpressionParserLeafTest, LTNullCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get());
@@ -280,8 +288,7 @@ TEST(MatchExpressionParserLeafTest, LTCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get());
@@ -298,8 +305,11 @@ TEST(MatchExpressionParserLeafTest, LTConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
@@ -316,8 +326,7 @@ TEST(MatchExpressionParserLeafTest, LTConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleGTE1) {
BSONObj query = BSON("x" << BSON("$gte" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -329,8 +338,7 @@ TEST(MatchExpressionParserLeafTest, GTENullCollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get());
@@ -342,8 +350,7 @@ TEST(MatchExpressionParserLeafTest, GTECollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get());
@@ -360,8 +367,11 @@ TEST(MatchExpressionParserLeafTest, GTEConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
@@ -380,8 +390,7 @@ TEST(MatchExpressionParserLeafTest, GTEConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleLTE1) {
BSONObj query = BSON("x" << BSON("$lte" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -393,8 +402,7 @@ TEST(MatchExpressionParserLeafTest, LTENullCollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get());
@@ -406,8 +414,7 @@ TEST(MatchExpressionParserLeafTest, LTECollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get());
@@ -424,8 +431,11 @@ TEST(MatchExpressionParserLeafTest, LTEConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
@@ -444,8 +454,7 @@ TEST(MatchExpressionParserLeafTest, LTEConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleNE1) {
BSONObj query = BSON("x" << BSON("$ne" << 2));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -457,8 +466,7 @@ TEST(MatchExpressionParserLeafTest, NENullCollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -472,8 +480,7 @@ TEST(MatchExpressionParserLeafTest, NECollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -492,8 +499,11 @@ TEST(MatchExpressionParserLeafTest, NEConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
@@ -510,36 +520,34 @@ TEST(MatchExpressionParserLeafTest, NEConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleModBad1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3)));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2 << 4)));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY("q" << 2)));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << 3));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON("a" << 1 << "b" << 2)));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, SimpleMod1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5)));
@@ -550,8 +558,7 @@ TEST(MatchExpressionParserLeafTest, SimpleMod1) {
TEST(MatchExpressionParserLeafTest, SimpleModNotNumber) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(2 << "r")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -571,8 +578,11 @@ TEST(MatchExpressionParserLeafTest, ModConstantExprFails) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(BSON_ARRAY(10 << 2)));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
}
@@ -581,8 +591,7 @@ TEST(MatchExpressionParserLeafTest, IdCollation) {
BSONObj query = BSON("$id"
<< "string");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -593,8 +602,7 @@ TEST(MatchExpressionParserLeafTest, IdNullCollation) {
BSONObj query = BSON("$id"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -611,8 +619,11 @@ TEST(MatchExpressionParserLeafTest, IdConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
@@ -622,8 +633,7 @@ TEST(MatchExpressionParserLeafTest, RefCollation) {
BSONObj query = BSON("$ref"
<< "coll");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -640,8 +650,11 @@ TEST(MatchExpressionParserLeafTest, RefConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(std::string("colName")));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
@@ -651,8 +664,7 @@ TEST(MatchExpressionParserLeafTest, DbCollation) {
BSONObj query = BSON("$db"
<< "db");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -669,8 +681,11 @@ TEST(MatchExpressionParserLeafTest, DbConstantExpr) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(std::string("dbName")));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), collator, expCtx);
+ auto result = MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
@@ -679,8 +694,7 @@ TEST(MatchExpressionParserLeafTest, DbConstantExpr) {
TEST(MatchExpressionParserLeafTest, SimpleIN1) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(2 << 3)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -691,8 +705,7 @@ TEST(MatchExpressionParserLeafTest, SimpleIN1) {
TEST(MatchExpressionParserLeafTest, INNullCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get());
@@ -702,8 +715,7 @@ TEST(MatchExpressionParserLeafTest, INNullCollation) {
TEST(MatchExpressionParserLeafTest, INCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get());
@@ -720,8 +732,12 @@ TEST(MatchExpressionParserLeafTest, INConstantExprFails) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 2)));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx);
+ StatusWithMatchExpression result =
+ MatchExpressionParser::parse(query,
+ &collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
@@ -731,8 +747,11 @@ TEST(MatchExpressionParserLeafTest, INConstantExprFails) {
varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx);
+ result = MatchExpressionParser::parse(query,
+ &collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
}
@@ -746,8 +765,7 @@ TEST(MatchExpressionParserLeafTest, INSingleDBRef) {
<< "$db"
<< "db"))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -829,8 +847,7 @@ TEST(MatchExpressionParserLeafTest, INMultipleDBRef) {
<< "$db"
<< "db"))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -971,8 +988,7 @@ TEST(MatchExpressionParserLeafTest, INDBRefWithOptionalField1) {
<< "foo"
<< 12345))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -1007,23 +1023,22 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, collator);
// second field is not $id
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$foo"
<< 1))));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
OID oid = OID::gen();
// missing $ref field
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$id" << oid << "foo" << 3))));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
// missing $id and $ref field
@@ -1031,39 +1046,35 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) {
<< "test"
<< "foo"
<< 3))));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, INExpressionDocument) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$foo" << 1))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, INNotArray) {
BSONObj query = BSON("x" << BSON("$in" << 5));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, INUndefined) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSONUndefined)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, INNotElemMatch) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$elemMatch" << 1))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1075,8 +1086,7 @@ TEST(MatchExpressionParserLeafTest, INRegexTooLong) {
operand.appendArray("$in", inArray.obj());
BSONObj query = BSON("x" << operand.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1084,8 +1094,7 @@ TEST(MatchExpressionParserLeafTest, INRegexTooLong2) {
string tooLargePattern(50 * 1000, 'z');
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$regex" << tooLargePattern))));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1099,8 +1108,7 @@ TEST(MatchExpressionParserLeafTest, INRegexStuff) {
BSONObj query = BSON("a" << operand.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
BSONObj matchFirst = BSON("a"
@@ -1126,8 +1134,7 @@ TEST(MatchExpressionParserLeafTest, INRegexStuff) {
TEST(MatchExpressionParserLeafTest, SimpleNIN1) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY(2 << 3)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -1138,16 +1145,14 @@ TEST(MatchExpressionParserLeafTest, SimpleNIN1) {
TEST(MatchExpressionParserLeafTest, NINNotArray) {
BSONObj query = BSON("x" << BSON("$nin" << 5));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, NINNullCollation) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY("string")));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -1159,8 +1164,7 @@ TEST(MatchExpressionParserLeafTest, NINNullCollation) {
TEST(MatchExpressionParserLeafTest, NINCollation) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -1179,8 +1183,12 @@ TEST(MatchExpressionParserLeafTest, NINConstantExprFails) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 2)));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx);
+ StatusWithMatchExpression result =
+ MatchExpressionParser::parse(query,
+ &collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
@@ -1190,8 +1198,11 @@ TEST(MatchExpressionParserLeafTest, NINConstantExprFails) {
varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(123));
- result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx);
+ result = MatchExpressionParser::parse(query,
+ &collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr);
ASSERT_NOT_OK(result.getStatus());
ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue);
}
@@ -1201,8 +1212,7 @@ TEST(MatchExpressionParserLeafTest, Regex1) {
b.appendRegex("x", "abc", "i");
BSONObj query = b.obj();
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -1219,8 +1229,7 @@ TEST(MatchExpressionParserLeafTest, Regex2) {
<< "$options"
<< "i"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -1237,8 +1246,7 @@ TEST(MatchExpressionParserLeafTest, Regex3) {
<< "$regex"
<< "abc"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -1256,27 +1264,26 @@ TEST(MatchExpressionParserLeafTest, RegexBad) {
<< "$optionas"
<< "i"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
// $regex does not with numbers
query = BSON("x" << BSON("$regex" << 123));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$regex" << BSON_ARRAY("abc")));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$optionas"
<< "i"));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$options"
<< "i"));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1284,8 +1291,7 @@ TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) {
BSONObj query = BSON("x" << BSON("$regex"
<< "^a\\x00b"));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
const auto value = "a\0b"_sd;
@@ -1305,8 +1311,7 @@ TEST(MatchExpressionParserLeafTest, RegexWithConstantExprFails) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(std::string("i")));
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
@@ -1318,7 +1323,7 @@ TEST(MatchExpressionParserLeafTest, RegexWithConstantExprFails) {
varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(std::string("abc")));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1327,8 +1332,7 @@ TEST(MatchExpressionParserLeafTest, ExistsYes1) {
b.appendBool("$exists", true);
BSONObj query = BSON("x" << b.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -1342,8 +1346,7 @@ TEST(MatchExpressionParserLeafTest, ExistsNO1) {
b.appendBool("$exists", false);
BSONObj query = BSON("x" << b.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -1355,8 +1358,7 @@ TEST(MatchExpressionParserLeafTest, ExistsNO1) {
TEST(MatchExpressionParserLeafTest, Type1) {
BSONObj query = BSON("x" << BSON("$type" << String));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -1367,8 +1369,7 @@ TEST(MatchExpressionParserLeafTest, Type1) {
TEST(MatchExpressionParserLeafTest, Type2) {
BSONObj query = BSON("x" << BSON("$type" << (double)NumberDouble));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -1378,8 +1379,7 @@ TEST(MatchExpressionParserLeafTest, Type2) {
TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) {
BSONObj query = BSON("x" << BSON("$type" << 1.5));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -1389,8 +1389,7 @@ TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) {
TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) {
BSONObj query = BSON("x" << BSON("$type" << mongo::NumberDecimal));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT_FALSE(result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -1400,8 +1399,7 @@ TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) {
TEST(MatchExpressionParserLeafTest, TypeNull) {
BSONObj query = BSON("x" << BSON("$type" << jstNULL));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSONObj()));
@@ -1416,48 +1414,35 @@ TEST(MatchExpressionParserLeafTest, TypeBadType) {
b.append("$type", (JSTypeMax + 1));
BSONObj query = BSON("x" << b.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeBad) {
BSONObj query = BSON("x" << BSON("$type" << BSON("x" << 1)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeBadString) {
const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: null}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: {}}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$type: ObjectId('000000000000000000000000')}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: []}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ MatchExpressionParser::parse(fromjson("{a: {$type: null}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$type: true}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$type: {}}}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ fromjson("{a: {$type: ObjectId('000000000000000000000000')}}"), collator)
.getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: []}}"), collator).getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeStringnameDouble) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumberDouble = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'double'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumberDouble =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'double'}}"), collator);
ASSERT_OK(typeNumberDouble.getStatus());
TypeMatchExpression* tmeNumberDouble =
static_cast<TypeMatchExpression*>(typeNumberDouble.getValue().get());
@@ -1468,8 +1453,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameDouble) {
TEST(MatchExpressionParserLeafTest, TypeStringNameNumberDecimal) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumberDecimal = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'decimal'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumberDecimal =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'decimal'}}"), collator);
ASSERT_OK(typeNumberDecimal.getStatus());
TypeMatchExpression* tmeNumberDecimal =
static_cast<TypeMatchExpression*>(typeNumberDecimal.getValue().get());
@@ -1480,8 +1465,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringNameNumberDecimal) {
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberInt) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumberInt = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'int'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumberInt =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'int'}}"), collator);
ASSERT_OK(typeNumberInt.getStatus());
TypeMatchExpression* tmeNumberInt =
static_cast<TypeMatchExpression*>(typeNumberInt.getValue().get());
@@ -1492,8 +1477,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumberInt) {
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberLong) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumberLong = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'long'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumberLong =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'long'}}"), collator);
ASSERT_OK(typeNumberLong.getStatus());
TypeMatchExpression* tmeNumberLong =
static_cast<TypeMatchExpression*>(typeNumberLong.getValue().get());
@@ -1504,8 +1489,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumberLong) {
TEST(MatchExpressionParserLeafTest, TypeStringnameString) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeString = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'string'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeString =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'string'}}"), collator);
ASSERT_OK(typeString.getStatus());
TypeMatchExpression* tmeString = static_cast<TypeMatchExpression*>(typeString.getValue().get());
ASSERT_EQ(tmeString->getBSONType(), BSONType::String);
@@ -1515,8 +1500,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameString) {
TEST(MatchExpressionParserLeafTest, TypeStringnamejstOID) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typejstOID = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'objectId'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typejstOID =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'objectId'}}"), collator);
ASSERT_OK(typejstOID.getStatus());
TypeMatchExpression* tmejstOID = static_cast<TypeMatchExpression*>(typejstOID.getValue().get());
ASSERT_EQ(tmejstOID->getBSONType(), BSONType::jstOID);
@@ -1526,8 +1511,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnamejstOID) {
TEST(MatchExpressionParserLeafTest, TypeStringnamejstNULL) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typejstNULL = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'null'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typejstNULL =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'null'}}"), collator);
ASSERT_OK(typejstNULL.getStatus());
TypeMatchExpression* tmejstNULL =
static_cast<TypeMatchExpression*>(typejstNULL.getValue().get());
@@ -1538,8 +1523,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnamejstNULL) {
TEST(MatchExpressionParserLeafTest, TypeStringnameBool) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeBool = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'bool'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeBool =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'bool'}}"), collator);
ASSERT_OK(typeBool.getStatus());
TypeMatchExpression* tmeBool = static_cast<TypeMatchExpression*>(typeBool.getValue().get());
ASSERT_EQ(tmeBool->getBSONType(), BSONType::Bool);
@@ -1549,8 +1534,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameBool) {
TEST(MatchExpressionParserLeafTest, TypeStringnameObject) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeObject = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'object'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeObject =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'object'}}"), collator);
ASSERT_OK(typeObject.getStatus());
TypeMatchExpression* tmeObject = static_cast<TypeMatchExpression*>(typeObject.getValue().get());
ASSERT_EQ(tmeObject->getBSONType(), BSONType::Object);
@@ -1560,8 +1545,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameObject) {
TEST(MatchExpressionParserLeafTest, TypeStringnameArray) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeArray = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'array'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeArray =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'array'}}"), collator);
ASSERT_OK(typeArray.getStatus());
TypeMatchExpression* tmeArray = static_cast<TypeMatchExpression*>(typeArray.getValue().get());
ASSERT_EQ(tmeArray->getBSONType(), BSONType::Array);
@@ -1571,8 +1556,8 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameArray) {
TEST(MatchExpressionParserLeafTest, TypeStringnameNumber) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
- fromjson("{a: {$type: 'number'}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumber =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'number'}}"), collator);
ASSERT_OK(typeNumber.getStatus());
TypeMatchExpression* tmeNumber = static_cast<TypeMatchExpression*>(typeNumber.getValue().get());
ASSERT_TRUE(tmeNumber->matchesBSON(fromjson("{a: 5.4}")));
@@ -1583,22 +1568,22 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumber) {
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeLessThanMinKeyFailsToParse) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
- fromjson("{a: {$type: -20}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumber =
+ MatchExpressionParser::parse(fromjson("{a: {$type: -20}}"), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeGreaterThanMaxKeyFailsToParse) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
- fromjson("{a: {$type: 400}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumber =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 400}}"), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeUnusedBetweenMinAndMaxFailsToParse) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
- fromjson("{a: {$type: 62}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression typeNumber =
+ MatchExpressionParser::parse(fromjson("{a: {$type: 62}}"), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
@@ -1611,8 +1596,7 @@ TEST(MatchExpressionParserLeafTest, ValidTypeCodesParseSuccessfully) {
for (auto type : validTypes) {
BSONObj predicate = BSON("a" << BSON("$type" << type));
const CollatorInterface* collator = nullptr;
- auto expression = MatchExpressionParser::parse(
- predicate, ExtensionsCallbackDisallowExtensions(), collator);
+ auto expression = MatchExpressionParser::parse(predicate, collator);
ASSERT_OK(expression.getStatus());
auto typeExpression = static_cast<TypeMatchExpression*>(expression.getValue().get());
ASSERT_EQ(type, typeExpression->getBSONType());
@@ -1628,8 +1612,7 @@ TEST(MatchExpressionParserLeafTest, TypeWithConstantExprFails) {
auto varId = expCtx->variablesParseState.defineVariable("userVar");
expCtx->variables.setValue(varId, Value(static_cast<int>(BSONType::NumberDouble)));
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_NOT_OK(result.getStatus());
}
@@ -1637,77 +1620,55 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidMask) {
const double k2Power53 = scalbn(1, 32);
const CollatorInterface* collator = nullptr;
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << 54)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<long long>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53 - 1)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << 54)), collator).getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<long long>::max())), collator)
+ .getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53)), collator)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53 - 1)), collator)
+ .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << 54)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<long long>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53 - 1)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << 54)), collator)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<long long>::max())), collator)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53)), collator)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53 - 1)), collator)
+ .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << 54)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<long long>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53 - 1)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << 54)), collator).getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<long long>::max())), collator)
+ .getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53)), collator)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53 - 1)), collator)
+ .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << 54)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<long long>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53 - 1)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << 54)), collator)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<long long>::max())), collator)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53)), collator)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53 - 1)), collator)
+ .getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidArray) {
@@ -1718,79 +1679,59 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidArray) {
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[3].type());
const CollatorInterface* collator = nullptr;
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0))), collator)
+ .getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0 << 1 << 2 << 3))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << bsonArrayLongLong)),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0))), collator)
+ .getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0 << 1 << 2 << 3))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << bsonArrayLongLong)),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0))), collator)
+ .getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0 << 1 << 2 << 3))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << bsonArrayLongLong)),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0))), collator)
+ .getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0 << 1 << 2 << 3))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << bsonArrayLongLong)),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
@@ -1800,7 +1741,6 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidBinData) {
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAllSet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
@@ -1808,14 +1748,12 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidBinData) {
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAnySet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
@@ -1823,496 +1761,308 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidBinData) {
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskType) {
const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: null}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: {}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ''}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: null}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: true}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: {}}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ''}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: null}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ''}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- fromjson("{a: {$bitsAllClear: ObjectId('000000000000000000000000')}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: null}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: true}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {}}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ''}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ fromjson("{a: {$bitsAllClear: ObjectId('000000000000000000000000')}}"), collator)
+ .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: null}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ''}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- fromjson("{a: {$bitsAnySet: ObjectId('000000000000000000000000')}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: null}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: true}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {}}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ''}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ fromjson("{a: {$bitsAnySet: ObjectId('000000000000000000000000')}}"), collator)
+ .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: null}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ''}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- fromjson("{a: {$bitsAnyClear: ObjectId('000000000000000000000000')}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: null}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: true}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {}}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ''}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ fromjson("{a: {$bitsAnyClear: ObjectId('000000000000000000000000')}}"), collator)
+ .getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskValue) {
const double kLongLongMaxAsDouble = scalbn(1, std::numeric_limits<long long>::digits);
const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: NaN}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: -54}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<double>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << kLongLongMaxAsDouble)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: NaN}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: -54}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<double>::max())), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: 2.5}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllSet" << kLongLongMaxAsDouble)), collator)
.getStatus());
-
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << Decimal128("2.5"))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: 2.5}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: NaN}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: -54}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<double>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAllSet" << Decimal128("2.5"))), collator)
.getStatus());
+
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: NaN}}"), collator).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << kLongLongMaxAsDouble)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: -54}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<double>::max())), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: 2.5}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllClear" << kLongLongMaxAsDouble)), collator)
.getStatus());
-
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << Decimal128("2.5"))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: 2.5}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: NaN}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: -54}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<double>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAllClear" << Decimal128("2.5"))), collator)
.getStatus());
+
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: NaN}}"), collator).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << kLongLongMaxAsDouble)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: -54}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<double>::max())), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: 2.5}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnySet" << kLongLongMaxAsDouble)), collator)
.getStatus());
-
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << Decimal128("2.5"))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: 2.5}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: NaN}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: -54}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<double>::max())),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ BSON("a" << BSON("$bitsAnySet" << Decimal128("2.5"))), collator)
.getStatus());
+
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: NaN}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: -54}}"), collator).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << kLongLongMaxAsDouble)),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<double>::max())), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: 2.5}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnyClear" << kLongLongMaxAsDouble)), collator)
.getStatus());
-
ASSERT_NOT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << Decimal128("2.5"))),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: 2.5}}"), collator).getStatus());
+
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnyClear" << Decimal128("2.5"))), collator)
+ .getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArray) {
const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [null]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [true]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ['']}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [[]]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [null]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [true]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ['']}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{}]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [[]]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"), collator).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllSet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [null]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [true]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ['']}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [{}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [[]]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [null]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [true]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ['']}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [{}]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [[]]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1]}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [null]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [true]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ['']}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [{}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [[]]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [null]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [true]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ['']}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [{}]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [[]]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"), collator).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnySet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [null]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [true]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [null]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ['']}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [true]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [{}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [[]]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ['']}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [{}]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [[]]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1]}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArrayValue) {
const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-54]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [NaN]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-54]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [NaN]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [1e100]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1e100]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-54]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-54]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [NaN]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [NaN]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [1e100]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1e100]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-54]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [NaN]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-54]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [NaN]}}"), collator).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [1e100]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1e100]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-54]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-54]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [NaN]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [NaN]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [1e100]}}"), collator)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1e100]}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1e100]}}"), collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
@@ -2325,27 +2075,31 @@ TEST(MatchExpressionParserLeafTest, BitTestWithConstantExprFails) {
expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 5)));
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{$expr: 'userVar'}]}}"),
- ExtensionsCallbackDisallowExtensions(),
collator,
- expCtx)
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {$expr: 'userVar'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator,
- expCtx)
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {$expr: 'userVar'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator,
- expCtx)
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {$expr: 'userVar'}}}"),
- ExtensionsCallbackDisallowExtensions(),
collator,
- expCtx)
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr)
.getStatus());
}
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_parser_test.cpp b/src/mongo/db/matcher/expression_parser_test.cpp
index 9026782ffdb..9f0276b7028 100644
--- a/src/mongo/db/matcher/expression_parser_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_test.cpp
@@ -36,15 +36,15 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
namespace mongo {
TEST(MatchExpressionParserTest, SimpleEQ1) {
BSONObj query = BSON("x" << 2);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -54,8 +54,7 @@ TEST(MatchExpressionParserTest, SimpleEQ1) {
TEST(MatchExpressionParserTest, Multiple1) {
BSONObj query = BSON("x" << 5 << "y" << BSON("$gt" << 5 << "$lt" << 8));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 7)));
@@ -68,24 +67,22 @@ TEST(MatchExpressionParserTest, Multiple1) {
TEST(AtomicMatchExpressionTest, AtomicOperator1) {
BSONObj query = BSON("x" << 5 << "$atomic" << BSON("$gt" << 5 << "$lt" << 8));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
query = BSON("x" << 5 << "$isolated" << 1);
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
query = BSON("x" << 5 << "y" << BSON("$isolated" << 1));
- result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserTest, MinDistanceWithoutNearFailsToParse) {
BSONObj query = fromjson("{loc: {$minDistance: 10}}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_FALSE(result.isOK());
}
@@ -229,31 +226,26 @@ TEST(StatusWithTest, Fib1) {
TEST(MatchExpressionParserTest, AlwaysFalseFailsToParseNonOneArguments) {
auto queryIntArgument = BSON("$alwaysFalse" << 0);
- auto expr = MatchExpressionParser::parse(
- queryIntArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto expr = MatchExpressionParser::parse(queryIntArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON("$alwaysFalse"
<< "");
- expr = MatchExpressionParser::parse(
- queryStringArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryStringArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON("$alwaysFalse" << 1.1);
- expr = MatchExpressionParser::parse(
- queryDoubleArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON("$alwaysFalse" << true);
- expr = MatchExpressionParser::parse(
- queryFalseArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryFalseArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserTest, AlwaysFalseParsesIntegerArgument) {
auto query = BSON("$alwaysFalse" << 1);
- auto expr =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto expr = MatchExpressionParser::parse(query, nullptr);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{}")));
@@ -263,35 +255,138 @@ TEST(MatchExpressionParserTest, AlwaysFalseParsesIntegerArgument) {
TEST(MatchExpressionParserTest, AlwaysTrueFailsToParseNonOneArguments) {
auto queryIntArgument = BSON("$alwaysTrue" << 0);
- auto expr = MatchExpressionParser::parse(
- queryIntArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto expr = MatchExpressionParser::parse(queryIntArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON("$alwaysTrue"
<< "");
- expr = MatchExpressionParser::parse(
- queryStringArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryStringArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON("$alwaysTrue" << 1.1);
- expr = MatchExpressionParser::parse(
- queryDoubleArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON("$alwaysTrue" << true);
- expr = MatchExpressionParser::parse(
- queryFalseArgument, ExtensionsCallbackDisallowExtensions(), nullptr);
+ expr = MatchExpressionParser::parse(queryFalseArgument, nullptr);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserTest, AlwaysTrueParsesIntegerArgument) {
auto query = BSON("$alwaysTrue" << 1);
- auto expr =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto expr = MatchExpressionParser::parse(query, nullptr);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{}")));
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{x: 1}")));
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{x: 'blah'}")));
}
+
+TEST(MatchExpressionParserTest, TextFailsToParseWhenDisallowed) {
+ auto query = fromjson("{$text: {$search: 'str'}}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, TextParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{$text: {$search: 'str'}}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kText)
+ .getStatus());
+}
+
+TEST(MatchExpressionParserTest, WhereFailsToParseWhenDisallowed) {
+ auto query = fromjson("{$where: 'this.a == this.b'}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, WhereParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{$where: 'this.a == this.b'}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kJavascript)
+ .getStatus());
+}
+
+TEST(MatchExpressionParserTest, NearSphereFailsToParseWhenDisallowed) {
+ auto query = fromjson("{a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, NearSphereParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kGeoNear)
+ .getStatus());
+}
+
+TEST(MatchExpressionParserTest, GeoNearFailsToParseWhenDisallowed) {
+ auto query = fromjson("{a: {$geoNear: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, GeoNearParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{a: {$geoNear: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kGeoNear)
+ .getStatus());
+}
+
+TEST(MatchExpressionParserTest, NearFailsToParseWhenDisallowed) {
+ auto query = fromjson("{a: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, NearParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{a: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kGeoNear)
+ .getStatus());
+}
+
+TEST(MatchExpressionParserTest, ExprFailsToParseWhenDisallowed) {
+ auto query = fromjson("{a: {$expr: 5}}");
+ const CollatorInterface* collator = nullptr;
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+}
+
+TEST(MatchExpressionParserTest, ExprParsesSuccessfullyWhenAllowed) {
+ auto query = fromjson("{a: {$expr: 5}}");
+ const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(MatchExpressionParser::parse(query,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kExpr)
+ .getStatus());
+}
}
diff --git a/src/mongo/db/matcher/expression_parser_tree.cpp b/src/mongo/db/matcher/expression_parser_tree.cpp
index b7ba5964253..1e4290fcdc9 100644
--- a/src/mongo/db/matcher/expression_parser_tree.cpp
+++ b/src/mongo/db/matcher/expression_parser_tree.cpp
@@ -43,6 +43,7 @@ Status MatchExpressionParser::_parseTreeList(const BSONObj& arr,
ListOfMatchExpression* out,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
if (arr.isEmpty())
return Status(ErrorCodes::BadValue, "$and/$or/$nor must be a nonempty array");
@@ -54,7 +55,8 @@ Status MatchExpressionParser::_parseTreeList(const BSONObj& arr,
if (e.type() != Object)
return Status(ErrorCodes::BadValue, "$or/$and/$nor entries need to be full objects");
- StatusWithMatchExpression sub = _parse(e.Obj(), collator, expCtx, topLevel);
+ StatusWithMatchExpression sub =
+ _parse(e.Obj(), collator, expCtx, allowedFeatures, topLevel);
if (!sub.isOK())
return sub.getStatus();
@@ -68,6 +70,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseNot(
const BSONElement& e,
const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ AllowedFeatureSet allowedFeatures,
bool topLevel) {
if (e.type() == RegEx) {
StatusWithMatchExpression s = _parseRegexElement(name, e, expCtx);
@@ -88,7 +91,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseNot(
return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot be empty");
std::unique_ptr<AndMatchExpression> theAnd = stdx::make_unique<AndMatchExpression>();
- Status s = _parseSub(name, notObject, theAnd.get(), collator, expCtx, topLevel);
+ Status s =
+ _parseSub(name, notObject, theAnd.get(), collator, expCtx, allowedFeatures, topLevel);
if (!s.isOK())
return StatusWithMatchExpression(s);
diff --git a/src/mongo/db/matcher/expression_parser_tree_test.cpp b/src/mongo/db/matcher/expression_parser_tree_test.cpp
index 1fbed8b69a6..d223a672c95 100644
--- a/src/mongo/db/matcher/expression_parser_tree_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_tree_test.cpp
@@ -36,15 +36,13 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
namespace mongo {
TEST(MatchExpressionParserTreeTest, OR1) {
BSONObj query = BSON("$or" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -57,8 +55,7 @@ TEST(MatchExpressionParserTreeTest, OREmbedded) {
BSONObj query1 = BSON("$or" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
BSONObj query2 = BSON("$or" << BSON_ARRAY(query1));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query2, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query2, collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -71,8 +68,7 @@ TEST(MatchExpressionParserTreeTest, OREmbedded) {
TEST(MatchExpressionParserTreeTest, AND1) {
BSONObj query = BSON("$and" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -86,8 +82,7 @@ TEST(MatchExpressionParserTreeTest, AND1) {
TEST(MatchExpressionParserTreeTest, NOREmbedded) {
BSONObj query = BSON("$nor" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -99,8 +94,7 @@ TEST(MatchExpressionParserTreeTest, NOREmbedded) {
TEST(MatchExpressionParserTreeTest, NOT1) {
BSONObj query = BSON("x" << BSON("$not" << BSON("$gt" << 5)));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -112,8 +106,7 @@ TEST(MatchExpressionParserLeafTest, NotRegex1) {
b.appendRegex("$not", "abc", "i");
BSONObj query = BSON("x" << b.obj());
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
diff --git a/src/mongo/db/matcher/expression_serialization_test.cpp b/src/mongo/db/matcher/expression_serialization_test.cpp
index 0f08fedebb7..6ab93f3e2dc 100644
--- a/src/mongo/db/matcher/expression_serialization_test.cpp
+++ b/src/mongo/db/matcher/expression_serialization_test.cpp
@@ -33,9 +33,9 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/matcher/matcher.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -54,9 +54,17 @@ BSONObj serialize(MatchExpression* match) {
}
TEST(SerializeBasic, AndExpressionWithOneChildSerializesCorrectly) {
- Matcher original(fromjson("{$and: [{x: 0}]}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$and: [{x: 0}]}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$and: [{x: {$eq: 0}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -68,10 +76,17 @@ TEST(SerializeBasic, AndExpressionWithOneChildSerializesCorrectly) {
}
TEST(SerializeBasic, AndExpressionWithTwoChildrenSerializesCorrectly) {
- Matcher original(
- fromjson("{$and: [{x: 1}, {x: 2}]}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$and: [{x: 1}, {x: 2}]}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$and: [{x: {$eq: 1}}, {x: {$eq: 2}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -83,10 +98,17 @@ TEST(SerializeBasic, AndExpressionWithTwoChildrenSerializesCorrectly) {
}
TEST(SerializeBasic, AndExpressionWithTwoIdenticalChildrenSerializesCorrectly) {
- Matcher original(
- fromjson("{$and: [{x: 1}, {x: 1}]}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$and: [{x: 1}, {x: 1}]}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$and: [{x: {$eq: 1}}, {x: {$eq: 1}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -98,10 +120,17 @@ TEST(SerializeBasic, AndExpressionWithTwoIdenticalChildrenSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionOr) {
- Matcher original(
- fromjson("{$or: [{x: 'A'}, {x: 'B'}]}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$or: [{x: 'A'}, {x: 'B'}]}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$or: [{x: {$eq: 'A'}}, {x: {$eq: 'B'}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -114,11 +143,17 @@ TEST(SerializeBasic, ExpressionOr) {
}
TEST(SerializeBasic, ExpressionElemMatchObjectSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$elemMatch: {a: {$gt: 0}, b: {$gt: 0}}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$elemMatch: {$and: [{a: {$gt: 0}}, {b: {$gt: 0}}]}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -131,11 +166,17 @@ TEST(SerializeBasic, ExpressionElemMatchObjectSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionElemMatchObjectWithEmptyStringSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{'': {$elemMatch: {a: {$gt: 0}, b: {$gt: 0}}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{'': {$elemMatch: {$and: [{a: {$gt: 0}}, {b: {$gt: 0}}]}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -148,11 +189,17 @@ TEST(SerializeBasic, ExpressionElemMatchObjectWithEmptyStringSerializesCorrectly
}
TEST(SerializeBasic, ExpressionElemMatchValueSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$elemMatch: {$lt: 1, $gt: -1}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$elemMatch: {$lt: 1, $gt: -1}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -167,13 +214,21 @@ TEST(SerializeBasic, ExpressionElemMatchValueSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionElemMatchValueWithRegexSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
const auto match = BSON("x" << BSON("$elemMatch" << BSON("$regex"
<< "abc"
<< "$options"
<< "i")));
- Matcher original(match, ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ Matcher original(match,
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), match);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -188,11 +243,17 @@ TEST(SerializeBasic, ExpressionElemMatchValueWithRegexSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionElemMatchValueWithEmptyStringSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$elemMatch: {$lt: 1, $gt: -1}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$elemMatch: {$lt: 1, $gt: -1}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -207,9 +268,17 @@ TEST(SerializeBasic, ExpressionElemMatchValueWithEmptyStringSerializesCorrectly)
}
TEST(SerializeBasic, ExpressionSizeSerializesCorrectly) {
- Matcher original(fromjson("{x: {$size: 2}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$size: 2}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$size: 2}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -221,9 +290,17 @@ TEST(SerializeBasic, ExpressionSizeSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionAllSerializesCorrectly) {
- Matcher original(fromjson("{x: {$all: [1, 2]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$all: [1, 2]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$and: [{x: {$eq: 1}}, {x: {$eq: 2}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -235,9 +312,17 @@ TEST(SerializeBasic, ExpressionAllSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionAllWithEmptyArraySerializesCorrectly) {
- Matcher original(fromjson("{x: {$all: []}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$all: []}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$alwaysFalse: 1}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -246,10 +331,17 @@ TEST(SerializeBasic, ExpressionAllWithEmptyArraySerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionAllWithRegex) {
- Matcher original(
- fromjson("{x: {$all: [/a.b.c/, /.d.e./]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$all: [/a.b.c/, /.d.e./]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$and" << BSON_ARRAY(BSON("x" << BSON("$regex"
@@ -266,9 +358,17 @@ TEST(SerializeBasic, ExpressionAllWithRegex) {
}
TEST(SerializeBasic, ExpressionEqSerializesCorrectly) {
- Matcher original(fromjson("{x: {$eq: {a: 1}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$eq: {a: 1}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$eq: {a: 1}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -283,9 +383,17 @@ TEST(SerializeBasic, ExpressionEqSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNeSerializesCorrectly) {
- Matcher original(fromjson("{x: {$ne: {a: 1}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$ne: {a: 1}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: {$eq: {a: 1}}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -297,12 +405,18 @@ TEST(SerializeBasic, ExpressionNeSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNeWithRegexObjectSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(BSON("x" << BSON("$ne" << BSON("$regex"
<< "abc"))),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$eq" << BSON("$regex"
<< "abc"))))));
@@ -316,9 +430,17 @@ TEST(SerializeBasic, ExpressionNeWithRegexObjectSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionLtSerializesCorrectly) {
- Matcher original(fromjson("{x: {$lt: 3}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$lt: 3}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$lt: 3}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -330,9 +452,17 @@ TEST(SerializeBasic, ExpressionLtSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionGtSerializesCorrectly) {
- Matcher original(fromjson("{x: {$gt: 3}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$gt: 3}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$gt: 3}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -344,9 +474,17 @@ TEST(SerializeBasic, ExpressionGtSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionGteSerializesCorrectly) {
- Matcher original(fromjson("{x: {$gte: 3}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$gte: 3}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$gte: 3}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -358,9 +496,17 @@ TEST(SerializeBasic, ExpressionGteSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionLteSerializesCorrectly) {
- Matcher original(fromjson("{x: {$lte: 3}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$lte: 3}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$lte: 3}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -372,9 +518,17 @@ TEST(SerializeBasic, ExpressionLteSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
- Matcher original(fromjson("{x: {$regex: 'a.b'}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$regex: 'a.b'}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("x" << BSON("$regex"
<< "a.b")));
@@ -388,9 +542,17 @@ TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
- Matcher original(fromjson("{x: /a.b/i}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: /a.b/i}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("x" << BSON("$regex"
<< "a.b"
@@ -406,9 +568,17 @@ TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
- Matcher original(fromjson("{x: /a.b/}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: /a.b/}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("x" << BSON("$regex"
<< "a.b")));
@@ -422,10 +592,17 @@ TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionRegexWithEqObjSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$eq: {$regex: 'a.b'}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$eq: {$regex: 'a.b'}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$eq: {$regex: 'a.b'}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -440,9 +617,17 @@ TEST(SerializeBasic, ExpressionRegexWithEqObjSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionModSerializesCorrectly) {
- Matcher original(fromjson("{x: {$mod: [2, 1]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$mod: [2, 1]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$mod: [2, 1]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -454,9 +639,17 @@ TEST(SerializeBasic, ExpressionModSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionExistsTrueSerializesCorrectly) {
- Matcher original(fromjson("{x: {$exists: true}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$exists: true}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$exists: true}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -468,9 +661,17 @@ TEST(SerializeBasic, ExpressionExistsTrueSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionExistsFalseSerializesCorrectly) {
- Matcher original(fromjson("{x: {$exists: false}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$exists: false}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: {$exists: true}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -482,9 +683,17 @@ TEST(SerializeBasic, ExpressionExistsFalseSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionInSerializesCorrectly) {
- Matcher original(fromjson("{x: {$in: [1, 2, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$in: [1, 2, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$in: [1, 2, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -499,9 +708,17 @@ TEST(SerializeBasic, ExpressionInSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionInWithEmptyArraySerializesCorrectly) {
- Matcher original(fromjson("{x: {$in: []}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$in: []}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$in: []}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -510,10 +727,17 @@ TEST(SerializeBasic, ExpressionInWithEmptyArraySerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionInWithRegexSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$in: [/\\d+/, /\\w+/]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$in: [/\\d+/, /\\w+/]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$in: [/\\d+/, /\\w+/]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -528,9 +752,17 @@ TEST(SerializeBasic, ExpressionInWithRegexSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNinSerializesCorrectly) {
- Matcher original(fromjson("{x: {$nin: [1, 2, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$nin: [1, 2, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: {$in: [1, 2, 3]}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -545,10 +777,17 @@ TEST(SerializeBasic, ExpressionNinSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNinWithRegexValueSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$nin: [/abc/, /def/, /xyz/]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$nin: [/abc/, /def/, /xyz/]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$nor: [{x: {$in: [/abc/, /def/, /xyz/]}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -563,10 +802,17 @@ TEST(SerializeBasic, ExpressionNinWithRegexValueSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionBitsAllSetSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$bitsAllSet: [1, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$bitsAllSet: [1, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$bitsAllSet: [1, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -578,10 +824,17 @@ TEST(SerializeBasic, ExpressionBitsAllSetSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionBitsAllClearSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$bitsAllClear: [1, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$bitsAllClear: [1, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$bitsAllClear: [1, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -593,10 +846,17 @@ TEST(SerializeBasic, ExpressionBitsAllClearSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionBitsAnySetSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$bitsAnySet: [1, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$bitsAnySet: [1, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$bitsAnySet: [1, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -608,10 +868,17 @@ TEST(SerializeBasic, ExpressionBitsAnySetSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionBitsAnyClearSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$bitsAnyClear: [1, 3]}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$bitsAnyClear: [1, 3]}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$bitsAnyClear: [1, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -626,9 +893,17 @@ TEST(SerializeBasic, ExpressionBitsAnyClearSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotSerializesCorrectly) {
- Matcher original(fromjson("{x: {$not: {$eq: 3}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: {$eq: 3}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{$and: [{x: {$eq: 3}}]}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -640,10 +915,17 @@ TEST(SerializeBasic, ExpressionNotSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithMultipleChildrenSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$not: {$lt: 1, $gt: 3}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: {$lt: 1, $gt: 3}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$nor: [{$and: [{x: {$lt: 1}}, {x: {$gt: 3}}]}]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -656,10 +938,17 @@ TEST(SerializeBasic, ExpressionNotWithMultipleChildrenSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithBitTestSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$not: {$bitsAnySet: [1, 3]}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: {$bitsAnySet: [1, 3]}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$nor: [{$and: [{x: {$bitsAnySet: [1, 3]}}]}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -672,10 +961,17 @@ TEST(SerializeBasic, ExpressionNotWithBitTestSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithRegexObjSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$not: {$regex: 'a.b'}}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: {$regex: 'a.b'}}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
<< "a.b")))));
@@ -689,9 +985,17 @@ TEST(SerializeBasic, ExpressionNotWithRegexObjSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithRegexValueSerializesCorrectly) {
- Matcher original(fromjson("{x: {$not: /a.b/}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: /a.b/}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
<< "a.b")))));
@@ -705,9 +1009,17 @@ TEST(SerializeBasic, ExpressionNotWithRegexValueSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithRegexValueAndOptionsSerializesCorrectly) {
- Matcher original(fromjson("{x: {$not: /a.b/i}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$not: /a.b/i}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
<< "a.b"
@@ -723,13 +1035,19 @@ TEST(SerializeBasic, ExpressionNotWithRegexValueAndOptionsSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNotWithGeoSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$not: {$geoIntersects: {$geometry: {type: 'Polygon', "
"coordinates: [[[0,0], [5,0], "
"[5, 5], [0, 5], [0, 0]]]}}}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
fromjson("{$nor: [{$and: [{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: "
@@ -752,10 +1070,17 @@ TEST(SerializeBasic, ExpressionNotWithGeoSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNorSerializesCorrectly) {
- Matcher original(
- fromjson("{$nor: [{x: 3}, {x: {$lt: 1}}]}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$nor: [{x: 3}, {x: {$lt: 1}}]}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: {$eq: 3}}, {x: {$lt: 1}}]}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -770,9 +1095,17 @@ TEST(SerializeBasic, ExpressionNorSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionTypeSerializesCorrectly) {
- Matcher original(fromjson("{x: {$type: 2}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$type: 2}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$type: 2}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -784,9 +1117,17 @@ TEST(SerializeBasic, ExpressionTypeSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionTypeWithNumberSerializesCorrectly) {
- Matcher original(fromjson("{x: {$type: 'number'}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$type: 'number'}}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$type: 'number'}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -798,10 +1139,8 @@ TEST(SerializeBasic, ExpressionTypeWithNumberSerializesCorrectly) {
}
TEST(SerializeInternalSchema, InternalSchemaTypeExpressionSerializesCorrectly) {
- Matcher original(
- fromjson("{x: {$_internalSchemaType: 2}}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ Matcher original(fromjson("{x: {$_internalSchemaType: 2}}"), kSimpleCollator);
+ Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaType: 2}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -813,11 +1152,8 @@ TEST(SerializeInternalSchema, InternalSchemaTypeExpressionSerializesCorrectly) {
}
TEST(SerializeInternalSchema, InternalSchemaTypeExpressionWithNumberSerializesCorrectly) {
- Matcher original(fromjson("{x: {$_internalSchemaType: 'number'}}"),
- ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ Matcher original(fromjson("{x: {$_internalSchemaType: 'number'}}"), kSimpleCollator);
+ Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaType: 'number'}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -829,9 +1165,17 @@ TEST(SerializeInternalSchema, InternalSchemaTypeExpressionWithNumberSerializesCo
}
TEST(SerializeBasic, ExpressionEmptySerializesCorrectly) {
- Matcher original(fromjson("{}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -840,10 +1184,17 @@ TEST(SerializeBasic, ExpressionEmptySerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionWhereSerializesCorrectly) {
- Matcher original(
- fromjson("{$where: 'this.a == this.b'}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$where: 'this.a == this.b'}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
BSONObjBuilder().appendCodeWScope("$where", "this.a == this.b", BSONObj()).obj());
@@ -851,20 +1202,34 @@ TEST(SerializeBasic, ExpressionWhereSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionWhereWithScopeSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(BSON("$where" << BSONCodeWScope("this.a == this.b", BSON("x" << 3))),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
BSON("$where" << BSONCodeWScope("this.a == this.b", BSON("x" << 3))));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeBasic, ExpressionCommentSerializesCorrectly) {
- Matcher original(fromjson("{$comment: 'Hello'}"), ExtensionsCallbackNoop(), kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$comment: 'Hello'}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -876,14 +1241,20 @@ TEST(SerializeBasic, ExpressionCommentSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionGeoWithinSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson(
"{x: {$geoWithin: {$geometry: "
"{type: 'Polygon', coordinates: [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]}}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
fromjson("{x: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[0,0], [10,0], "
@@ -898,14 +1269,20 @@ TEST(SerializeBasic, ExpressionGeoWithinSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionGeoIntersectsSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson(
"{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[0,0], [5,0], [5, "
"5], [0, 5], [0, 0]]]}}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
fromjson("{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[0,0], [5,0], "
@@ -927,13 +1304,19 @@ TEST(SerializeBasic, ExpressionGeoIntersectsSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNearSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson("{x: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}, $maxDistance: 10, "
"$minDistance: 1}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
fromjson("{x: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}, $maxDistance: 10, "
@@ -942,14 +1325,20 @@ TEST(SerializeBasic, ExpressionNearSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionNearSphereSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson(
"{x: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}, $maxDistance: 10, "
"$minDistance: 1}}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
fromjson("{x: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}, "
@@ -958,11 +1347,17 @@ TEST(SerializeBasic, ExpressionNearSphereSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionTextSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$text: {$search: 'a', $language: 'en', $caseSensitive: true}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$text: {$search: 'a', $language: 'en', $caseSensitive: true, "
"$diacriticSensitive: false}}"));
@@ -970,11 +1365,17 @@ TEST(SerializeBasic, ExpressionTextSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionTextWithDefaultLanguageSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$text: {$search: 'a', $caseSensitive: false}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{$text: {$search: 'a', $language: '', $caseSensitive: false, "
"$diacriticSensitive: false}}"));
@@ -982,110 +1383,162 @@ TEST(SerializeBasic, ExpressionTextWithDefaultLanguageSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionAlwaysTrueSerializesCorrectly) {
- Matcher original(
- fromjson("{$alwaysTrue: 1}"), ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$alwaysTrue: 1}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$alwaysTrue: 1}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeBasic, ExpressionAlwaysFalseSerializesCorrectly) {
- Matcher original(
- fromjson("{$alwaysFalse: 1}"), ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$alwaysFalse: 1}"),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$alwaysFalse: 1}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaAllElemMatchFromIndexSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaAllElemMatchFromIndex: [2, {y: 1}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$_internalSchemaAllElemMatchFromIndex: [2, {y: {$eq: 1}}]}}"));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinItemsSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMinItems: 1}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaMinItems: 1}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxItemsSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMaxItems: 1}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaMaxItems: 1}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaUniqueItemsSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaUniqueItems: true}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$_internalSchemaUniqueItems: true}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaObjectMatchSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaObjectMatch: {y: 1}}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$_internalSchemaObjectMatch: {y: {$eq: 1}}}}"));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinLengthSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMinLength: 1}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaMinLength: 1}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxLengthSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMaxLength: 1}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaMaxLength: 1}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$_internalSchemaCond: [{a: 1}, {b: 2}, {c: 3}]}}"),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
BSONObjBuilder builder;
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
@@ -1094,34 +1547,52 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) {
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinPropertiesSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{$_internalSchemaMinProperties: 1}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackDisallowExtensions(), collator);
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$_internalSchemaMinProperties: 1}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxPropertiesSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{$_internalSchemaMaxProperties: 1}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackDisallowExtensions(), collator);
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$_internalSchemaMaxProperties: 1}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaFmodSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson("{a: {$_internalSchemaFmod: [NumberDecimal('2.3'), NumberDecimal('1.1')]}}"),
+ kSimpleCollator,
+ expCtx,
ExtensionsCallbackNoop(),
- kSimpleCollator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), kSimpleCollator);
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ kSimpleCollator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(
*reserialized.getQuery(),
@@ -1134,13 +1605,19 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaFmodSerializesCorrectly) {
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaMatchArrayIndexSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
constexpr CollatorInterface* collator = nullptr;
Matcher original(fromjson("{a: {$_internalSchemaMatchArrayIndex:"
"{index: 2, namePlaceholder: 'i', expression: {i: {$lt: 3}}}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
- Matcher reserialized(
- serialize(original.getMatchExpression()), ExtensionsCallbackDisallowExtensions(), collator);
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher reserialized(serialize(original.getMatchExpression()),
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{a: {$_internalSchemaMatchArrayIndex:"
"{index: 2, namePlaceholder: 'i', expression: {i: {$lt: 3}}}}}"));
@@ -1154,11 +1631,8 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaAllowedPropertiesSerialize
namePlaceholder: 'i',
patternProperties: [{regex: /b/, expression: {i: {$type: 'number'}}}]
}})"),
- ExtensionsCallbackDisallowExtensions(),
kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()),
- ExtensionsCallbackDisallowExtensions(),
- kSimpleCollator);
+ Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson(R"({$_internalSchemaAllowedProperties: {
properties: ['a'],
namePlaceholder: 'i',
diff --git a/src/mongo/db/matcher/expression_text.h b/src/mongo/db/matcher/expression_text.h
index bb5dbfb77b1..2a3ac4a3c36 100644
--- a/src/mongo/db/matcher/expression_text.h
+++ b/src/mongo/db/matcher/expression_text.h
@@ -47,6 +47,21 @@ public:
return _ftsQuery;
}
+ bool matchesSingleElement(const BSONElement& e, MatchDetails* details = nullptr) const final {
+ // Text match expressions force the selection of the text index and always generate EXACT
+ // index bounds (which causes the MatchExpression node to be trimmed), so we don't currently
+ // implement any explicit text matching logic here. SERVER-17648 tracks the work to
+ // implement a real text matcher.
+ //
+ // TODO: simply returning 'true' here isn't quite correct. First, we should be overriding
+ // matches() instead of matchesSingleElement(), because the latter is only ever called if
+ // the matched document has an element with path "_fts". Second, there are scenarios where
+ // we will use the untrimmed expression tree for matching (for example, when deciding
+ // whether or not to retry an operation that throws WriteConflictException); in those cases,
+ // we won't be able to correctly determine whether or not the object matches the expression.
+ return true;
+ }
+
std::unique_ptr<MatchExpression> shallowClone() const final;
private:
diff --git a/src/mongo/db/matcher/expression_text_base.h b/src/mongo/db/matcher/expression_text_base.h
index 65b38f90b43..045a9d88a32 100644
--- a/src/mongo/db/matcher/expression_text_base.h
+++ b/src/mongo/db/matcher/expression_text_base.h
@@ -63,21 +63,6 @@ public:
// Methods inherited from MatchExpression.
//
- bool matchesSingleElement(const BSONElement& e, MatchDetails* details = nullptr) const final {
- // Text match expressions force the selection of the text index and always generate EXACT
- // index bounds (which causes the MatchExpression node to be trimmed), so we don't currently
- // implement any explicit text matching logic here. SERVER-17648 tracks the work to
- // implement a real text matcher.
- //
- // TODO: simply returning 'true' here isn't quite correct. First, we should be overriding
- // matches() instead of matchesSingleElement(), because the latter is only ever called if
- // the matched document has an element with path "_fts". Second, there are scenarios where
- // we will use the untrimmed expression tree for matching (for example, when deciding
- // whether or not to retry an operation that throws WriteConflictException); in those cases,
- // we won't be able to correctly determine whether or not the object matches the expression.
- return true;
- }
-
void debugString(StringBuilder& debug, int level = 0) const final;
void serialize(BSONObjBuilder* out) const final;
diff --git a/src/mongo/db/matcher/expression_text_noop.h b/src/mongo/db/matcher/expression_text_noop.h
index 8e01d40e70b..429fecff05d 100644
--- a/src/mongo/db/matcher/expression_text_noop.h
+++ b/src/mongo/db/matcher/expression_text_noop.h
@@ -41,6 +41,10 @@ public:
return _ftsQuery;
}
+ bool matchesSingleElement(const BSONElement& e, MatchDetails* details = nullptr) const final {
+ MONGO_UNREACHABLE;
+ }
+
std::unique_ptr<MatchExpression> shallowClone() const final;
private:
diff --git a/src/mongo/db/matcher/expression_where_noop.cpp b/src/mongo/db/matcher/expression_where_noop.cpp
index 23bb7c287e5..c65bf70019c 100644
--- a/src/mongo/db/matcher/expression_where_noop.cpp
+++ b/src/mongo/db/matcher/expression_where_noop.cpp
@@ -40,7 +40,7 @@ WhereNoOpMatchExpression::WhereNoOpMatchExpression(WhereParams params)
: WhereMatchExpressionBase(std::move(params)) {}
bool WhereNoOpMatchExpression::matches(const MatchableDocument* doc, MatchDetails* details) const {
- return false;
+ MONGO_UNREACHABLE;
}
std::unique_ptr<MatchExpression> WhereNoOpMatchExpression::shallowClone() const {
diff --git a/src/mongo/db/matcher/expression_with_placeholder.cpp b/src/mongo/db/matcher/expression_with_placeholder.cpp
index 34771d2cc8a..97158b6ab33 100644
--- a/src/mongo/db/matcher/expression_with_placeholder.cpp
+++ b/src/mongo/db/matcher/expression_with_placeholder.cpp
@@ -32,8 +32,6 @@
#include <regex>
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
-
namespace mongo {
namespace {
@@ -105,8 +103,7 @@ const std::regex ExpressionWithPlaceholder::placeholderRegex("^[a-z][a-zA-Z0-9]*
// static
StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> ExpressionWithPlaceholder::parse(
BSONObj rawFilter, const CollatorInterface* collator) {
- StatusWithMatchExpression statusWithFilter =
- MatchExpressionParser::parse(rawFilter, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithFilter = MatchExpressionParser::parse(rawFilter, collator);
if (!statusWithFilter.isOK()) {
return statusWithFilter.getStatus();
diff --git a/src/mongo/db/matcher/expression_with_placeholder_test.cpp b/src/mongo/db/matcher/expression_with_placeholder_test.cpp
index 8fd5f4e456f..bb8abef57ef 100644
--- a/src/mongo/db/matcher/expression_with_placeholder_test.cpp
+++ b/src/mongo/db/matcher/expression_with_placeholder_test.cpp
@@ -30,7 +30,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_with_placeholder.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/unittest.h"
@@ -178,6 +177,21 @@ TEST(ExpressionWithPlaceholderTest, WhereExpressionFailsToParse) {
ASSERT_NOT_OK(status.getStatus());
}
+TEST(ExpressionWithPlaceholderTest, GeoNearExpressionFailsToParse) {
+ const CollatorInterface* collator = nullptr;
+ auto rawFilter =
+ fromjson("{i: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ ASSERT_NOT_OK(status.getStatus());
+}
+
+TEST(ExpressionWithPlaceholderTest, ExprExpressionFailsToParse) {
+ const CollatorInterface* collator = nullptr;
+ auto rawFilter = fromjson("{i: {$expr: 5}}");
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ ASSERT_NOT_OK(status.getStatus());
+}
+
TEST(ExpressionWithPlaceholderTest, EquivalentIfPlaceholderAndExpressionMatch) {
constexpr auto collator = nullptr;
auto rawFilter1 = fromjson("{i: 5}}");
diff --git a/src/mongo/db/matcher/extensions_callback_disallow_extensions.cpp b/src/mongo/db/matcher/extensions_callback_disallow_extensions.cpp
deleted file mode 100644
index 2c68c97a23a..00000000000
--- a/src/mongo/db/matcher/extensions_callback_disallow_extensions.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (C) 2015 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
-
-namespace mongo {
-
-StatusWithMatchExpression ExtensionsCallbackDisallowExtensions::parseWhere(
- BSONElement where) const {
- return {Status(ErrorCodes::NoMatchParseContext, "no context for parsing $where")};
-}
-
-StatusWithMatchExpression ExtensionsCallbackDisallowExtensions::parseText(BSONElement text) const {
- return {Status(ErrorCodes::NoMatchParseContext, "no context for parsing $text")};
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/matcher/extensions_callback_disallow_extensions.h b/src/mongo/db/matcher/extensions_callback_disallow_extensions.h
deleted file mode 100644
index c641aecd0d1..00000000000
--- a/src/mongo/db/matcher/extensions_callback_disallow_extensions.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Copyright (C) 2015 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include "mongo/db/matcher/extensions_callback.h"
-
-namespace mongo {
-
-/**
- * ExtensionsCallbackDisallowExtensions produces an error during parsing if expressions which
- * require context are present. This implementation of ExtensionsCallback should be used if you wish
- * to explicitly ban the use of query language "extensions" such as $text and $where.
- */
-class ExtensionsCallbackDisallowExtensions : public ExtensionsCallback {
-public:
- /**
- * Always returns an error status.
- */
- StatusWithMatchExpression parseText(BSONElement text) const final;
-
- /**
- * Always returns an error status.
- */
- StatusWithMatchExpression parseWhere(BSONElement where) const final;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/matcher/matcher.cpp b/src/mongo/db/matcher/matcher.cpp
index faf0f6f1170..5648a4f15d5 100644
--- a/src/mongo/db/matcher/matcher.cpp
+++ b/src/mongo/db/matcher/matcher.cpp
@@ -42,11 +42,13 @@
namespace mongo {
Matcher::Matcher(const BSONObj& pattern,
+ const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback,
- const CollatorInterface* collator)
+ const MatchExpressionParser::AllowedFeatureSet allowedFeatures)
: _pattern(pattern) {
- StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(pattern, extensionsCallback, collator);
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
+ pattern, collator, expCtx, extensionsCallback, allowedFeatures);
uassert(16810,
mongoutils::str::stream() << "bad query: " << statusWithMatcher.getStatus().toString(),
statusWithMatcher.isOK());
diff --git a/src/mongo/db/matcher/matcher.h b/src/mongo/db/matcher/matcher.h
index e37a6a0a3b5..382b0dd4e0d 100644
--- a/src/mongo/db/matcher/matcher.h
+++ b/src/mongo/db/matcher/matcher.h
@@ -36,6 +36,7 @@
#include "mongo/bson/bsonobj.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/matcher/match_details.h"
@@ -54,8 +55,11 @@ public:
* 'collator' must outlive the returned Matcher and any MatchExpression cloned from it.
*/
explicit Matcher(const BSONObj& pattern,
- const ExtensionsCallback& extensionsCallback,
- const CollatorInterface* collator);
+ const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+ MatchExpressionParser::kBanAllSpecialFeatures);
bool matches(const BSONObj& doc, MatchDetails* details = NULL) const;
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
index a0e0d6573ba..87c0896193a 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp
@@ -31,7 +31,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h"
#include "mongo/unittest/unittest.h"
@@ -42,16 +41,14 @@ constexpr CollatorInterface* kSimpleCollator = nullptr;
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesEmptyQuery) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3 << 4))));
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesValidQueries) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3 << 4))));
@@ -63,24 +60,21 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesValidQueries) {
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, RejectsNonArrayElements) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(BSON("a" << BSON("a" << 1))));
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesArraysWithLessElementsThanIndex) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1))));
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, NestedArraysMatchSubexpression) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(
expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << BSON_ARRAY(3 << 4) << 4))));
@@ -92,8 +86,7 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, NestedArraysMatchSubexp
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchedQueriesWithDottedPaths) {
auto query = fromjson("{'a.b': {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(
expr.getValue()->matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3 << 4)))));
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
index b00d45d9172..e19a5bc2637 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp
@@ -30,7 +30,6 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h"
#include "mongo/unittest/unittest.h"
@@ -41,8 +40,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, MatchesObjectsWithListedPro
auto filter = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a', 'b'],"
"namePlaceholder: 'i', patternProperties: [], otherwise: {i: 0}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: 1, b: 1}")));
@@ -61,8 +59,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, MatchesObjectsWithMatchingP
],
otherwise: {i: {$type: 'string'}}
}})");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{puppies: 2, kittens: 3, phoneNum: 1234}")));
@@ -75,8 +72,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression,
auto filter = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a'], namePlaceholder: 'a',"
"patternProperties: [{regex: /a/, expression: {a: {$gt: 5}}}], otherwise: {a: 0}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: 6}")));
@@ -95,8 +91,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, OtherwiseEnforcedWhenApprop
],
otherwise: {i: {$type: 'string'}}
}})");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: 'bar'}")));
@@ -107,8 +102,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, EquivalentToClone) {
auto filter = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a'], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {i: 1}}], otherwise: {i: 7}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
auto clone = expr.getValue()->shallowClone();
ASSERT_TRUE(expr.getValue()->equivalent(clone.get()));
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp
index d8a1dc63871..b1cbb03d18a 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp
@@ -30,7 +30,6 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_cond.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
#include "mongo/unittest/unittest.h"
@@ -46,14 +45,11 @@ std::unique_ptr<InternalSchemaCondMatchExpression> createCondMatchExpression(BSO
auto cond = stdx::make_unique<InternalSchemaCondMatchExpression>();
const CollatorInterface* kSimpleCollator = nullptr;
- auto conditionExpr = MatchExpressionParser::parse(
- condition, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto conditionExpr = MatchExpressionParser::parse(condition, kSimpleCollator);
ASSERT_OK(conditionExpr.getStatus());
- auto thenBranchExpr = MatchExpressionParser::parse(
- thenBranch, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto thenBranchExpr = MatchExpressionParser::parse(thenBranch, kSimpleCollator);
ASSERT_OK(thenBranchExpr.getStatus());
- auto elseBranchExpr = MatchExpressionParser::parse(
- elseBranch, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto elseBranchExpr = MatchExpressionParser::parse(elseBranch, kSimpleCollator);
cond->init({{std::move(conditionExpr.getValue()),
std::move(thenBranchExpr.getValue()),
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
index 0f6dc702287..87c1d847beb 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp
@@ -31,7 +31,6 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/expression_with_placeholder.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_match_array_index.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/unittest.h"
@@ -44,8 +43,7 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, RejectsNonArrays) {
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$gt: 7}}}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: 'blah'}")));
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: 7}")));
@@ -56,8 +54,7 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesArraysWithMatchingElem
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$elemMatch: {'bar': 7}}}}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: [[{bar: 7}], [{bar: 5}]]}")));
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: [[{bar: [3, 5, 7]}], [{bar: 5}]]}")));
@@ -65,8 +62,7 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesArraysWithMatchingElem
filter = fromjson(
"{baz: {$_internalSchemaMatchArrayIndex:"
"{index: 2, namePlaceholder: 'i', expression: {i: {$type: 'string'}}}}}");
- expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{baz: [0, 1, '2']}")));
}
@@ -75,16 +71,14 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, DoesNotMatchArrayIfMatchingEl
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$lte: 7}}}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: [33, 0, 1, 2]}")));
filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 1, namePlaceholder: 'i', expression: {i: {$lte: 7}}}}}");
- expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: [0, 99, 1, 2]}")));
}
@@ -93,16 +87,14 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesIfNotEnoughArrayElemen
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: 1}}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: []}")));
filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 4, namePlaceholder: 'i', expression: {i: 1}}}}");
- expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: ['no', 'no', 'no', 'no']}")));
}
@@ -111,8 +103,7 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, EquivalentToClone) {
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}");
- auto expr = MatchExpressionParser::parse(
- filter, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
ASSERT_OK(expr.getStatus());
auto clone = expr.getValue()->shallowClone();
ASSERT_TRUE(expr.getValue()->equivalent(clone.get()));
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
index 89a95e7eff3..d195b901af6 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp
@@ -29,7 +29,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
@@ -40,8 +39,7 @@ namespace mongo {
namespace {
TEST(InternalSchemaObjectMatchExpression, RejectsNonObjectElements) {
- auto subExpr = MatchExpressionParser::parse(
- BSON("b" << 1), ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto subExpr = MatchExpressionParser::parse(BSON("b" << 1), nullptr);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -56,7 +54,6 @@ TEST(InternalSchemaObjectMatchExpression, RejectsNonObjectElements) {
TEST(InternalSchemaObjectMatchExpression, RejectsObjectsThatDontMatch) {
auto subExpr = MatchExpressionParser::parse(BSON("b" << BSON("$type"
<< "string")),
- ExtensionsCallbackDisallowExtensions(),
nullptr);
ASSERT_OK(subExpr.getStatus());
@@ -70,7 +67,6 @@ TEST(InternalSchemaObjectMatchExpression, RejectsObjectsThatDontMatch) {
TEST(InternalSchemaObjectMatchExpression, AcceptsObjectsThatMatch) {
auto subExpr = MatchExpressionParser::parse(BSON("b" << BSON("$type"
<< "string")),
- ExtensionsCallbackDisallowExtensions(),
nullptr);
ASSERT_OK(subExpr.getStatus());
@@ -92,7 +88,6 @@ TEST(InternalSchemaObjectMatchExpression, AcceptsObjectsThatMatch) {
TEST(InternalSchemaObjectMatchExpression, DottedPathAcceptsObjectsThatMatch) {
auto subExpr = MatchExpressionParser::parse(BSON("b.c.d" << BSON("$type"
<< "string")),
- ExtensionsCallbackDisallowExtensions(),
nullptr);
ASSERT_OK(subExpr.getStatus());
@@ -107,8 +102,7 @@ TEST(InternalSchemaObjectMatchExpression, DottedPathAcceptsObjectsThatMatch) {
}
TEST(InternalSchemaObjectMatchExpression, EmptyMatchAcceptsAllObjects) {
- auto subExpr =
- MatchExpressionParser::parse(BSONObj(), ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto subExpr = MatchExpressionParser::parse(BSONObj(), nullptr);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -130,8 +124,7 @@ TEST(InternalSchemaObjectMatchExpression, NestedObjectMatchReturnsCorrectPath) {
" $or: [{c: {$type: 'string'}}, {c: {$gt: 0}}]"
" }}}"
" }}}");
- auto objMatch =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto objMatch = MatchExpressionParser::parse(query, nullptr);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->path(), "a");
@@ -145,8 +138,7 @@ TEST(InternalSchemaObjectMatchExpression, MatchesNestedObjectMatch) {
" c: 3"
" }}}"
" }}}");
- auto objMatch =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto objMatch = MatchExpressionParser::parse(query, nullptr);
ASSERT_OK(objMatch.getStatus());
ASSERT_FALSE(objMatch.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -160,20 +152,20 @@ TEST(InternalSchemaObjectMatchExpression, EquivalentReturnsCorrectResults) {
" {a: {$_internalSchemaObjectMatch: {"
" b: 3"
" }}}");
- Matcher objectMatch(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ Matcher objectMatch(query, nullptr);
query = fromjson(
" {a: {$_internalSchemaObjectMatch: {"
" b: {$eq: 3}"
" }}}");
- Matcher objectMatchEq(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ Matcher objectMatchEq(query, nullptr);
ASSERT_TRUE(objectMatch.getMatchExpression()->equivalent(objectMatchEq.getMatchExpression()));
query = fromjson(
" {a: {$_internalSchemaObjectMatch: {"
" c: {$eq: 3}"
" }}}");
- Matcher objectMatchNotEq(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ Matcher objectMatchNotEq(query, nullptr);
ASSERT_FALSE(
objectMatch.getMatchExpression()->equivalent(objectMatchNotEq.getMatchExpression()));
}
@@ -184,8 +176,7 @@ TEST(InternalSchemaObjectMatchExpression, SubExpressionRespectsCollator) {
"{a: {$_internalSchemaObjectMatch: {"
" b: {$eq: 'FOO'}"
"}}}");
- auto objectMatch =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
+ auto objectMatch = MatchExpressionParser::parse(query, &collator);
ASSERT_OK(objectMatch.getStatus());
ASSERT_TRUE(objectMatch.getValue()->matchesBSON(fromjson("{a: {b: 'FOO'}}")));
@@ -195,8 +186,7 @@ TEST(InternalSchemaObjectMatchExpression, SubExpressionRespectsCollator) {
TEST(InternalSchemaObjectMatchExpression, RejectsArraysContainingMatchingSubObject) {
auto query = fromjson("{a: {$_internalSchemaObjectMatch: {b: 1}}}");
- auto objMatch =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), nullptr);
+ auto objMatch = MatchExpressionParser::parse(query, nullptr);
ASSERT_OK(objMatch.getStatus());
ASSERT_FALSE(objMatch.getValue()->matchesBSON(fromjson("{a: 1}")));
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp
index 2e2efe50327..37f6ff4f6c2 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp
@@ -33,7 +33,6 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_xor.h"
#include "mongo/unittest/unittest.h"
@@ -50,8 +49,7 @@ TEST(InternalSchemaXorOp, MatchesNothingWhenHasNoClauses) {
TEST(InternalSchemaXorOp, MatchesSingleClause) {
BSONObj matchPredicate = fromjson("{$_internalSchemaXor: [{a: { $ne: 5 }}]}");
const CollatorInterface* collator = nullptr;
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), collator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << 4)));
@@ -65,8 +63,7 @@ TEST(InternalSchemaXorOp, MatchesThreeClauses) {
BSONObj matchPredicate =
fromjson("{$_internalSchemaXor: [{a: { $gt: 10 }}, {a: { $lt: 0 }}, {b: 0}]}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), collator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, collator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << -1)));
@@ -84,8 +81,7 @@ TEST(InternalSchemaXorOp, DoesNotUseElemMatchKey) {
BSONObj matchPredicate = fromjson("{$_internalSchemaXor: [{a: 1}, {b: 2}]}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), collator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, collator);
MatchDetails details;
details.requestElemMatchKey();
ASSERT_OK(expr.getStatus());
diff --git a/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp b/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp
index 74bded78933..af86c2928eb 100644
--- a/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp
@@ -32,7 +32,6 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/expression_type.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/schema/expression_internal_schema_max_items.h"
#include "mongo/db/matcher/schema/expression_internal_schema_max_length.h"
#include "mongo/db/matcher/schema/expression_internal_schema_min_items.h"
@@ -49,8 +48,7 @@ constexpr CollatorInterface* kSimpleCollator = nullptr;
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -61,8 +59,7 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -73,8 +70,7 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -85,8 +81,7 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDoubleArgumentAsInt
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -97,8 +92,7 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -109,8 +103,7 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -122,8 +115,7 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -134,8 +126,7 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDoubleArgumentAsInt
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -146,31 +137,26 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, UniqueItemsFailsToParseNonTrueArguments) {
auto queryIntArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << 0));
- auto expr = MatchExpressionParser::parse(
- queryIntArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(queryIntArgument, kSimpleCollator);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaUniqueItems"
<< ""));
- expr = MatchExpressionParser::parse(
- queryStringArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << 1.0));
- expr = MatchExpressionParser::parse(
- queryDoubleArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << false));
- expr = MatchExpressionParser::parse(
- queryFalseArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, UniqueItemsParsesTrueBooleanArgument) {
auto query = BSON("x" << BSON("$_internalSchemaUniqueItems" << true));
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{x: 1}")));
@@ -184,20 +170,17 @@ TEST(MatchExpressionParserSchemaTest, UniqueItemsParsesTrueBooleanArgument) {
TEST(MatchExpressionParserSchemaTest, ObjectMatchOnlyAcceptsAnObjectArgument) {
auto query = BSON("a" << BSON("$_internalSchemaObjectMatch" << 1));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
query = BSON("a" << BSON("$_internalSchemaObjectMatch"
<< "string"));
- result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
query = BSON(
"a" << BSON("$_internalSchemaObjectMatch" << BSON_ARRAY(BSON("a" << 1) << BSON("b" << 1))));
- result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
}
@@ -207,8 +190,7 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchCorrectlyParsesObjects) {
" b: {$gte: 0}"
" }}"
"}");
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT_FALSE(result.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -225,8 +207,7 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchCorrectlyParsesNestedObjectMatc
" $or: [{c: {$type: 'string'}}, {c: {$gt: 0}}]"
" }}"
"}}}");
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_TRUE(result.isOK());
ASSERT_FALSE(result.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -243,8 +224,7 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchSubExprRejectsTopLevelOperators
"{a: {$_internalSchemaObjectMatch: {"
" $isolated: 1"
"}}}");
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_EQ(result.getStatus(), ErrorCodes::BadValue);
}
@@ -253,8 +233,7 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchSubExprRejectsTopLevelOperators
//
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -267,8 +246,7 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -281,8 +259,7 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -295,8 +272,7 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDoubleArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -310,29 +286,24 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDecimalArgumentAsI
TEST(MatchExpressionParserSchemaTest, MinLengthFailsToParseNonIntegerArguments) {
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaMinLength"
<< "abc"));
- auto expr = MatchExpressionParser::parse(
- queryStringArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryEmptyStringArgument = BSON("x" << BSON("$_internalSchemaMinLength"
<< ""));
- expr = MatchExpressionParser::parse(
- queryEmptyStringArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryEmptyStringArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaMinLength" << 1.5));
- expr = MatchExpressionParser::parse(
- queryDoubleArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaMinLength" << false));
- expr = MatchExpressionParser::parse(
- queryFalseArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryArrArgument = BSON("x" << BSON("$_internalSchemaMinLength" << BSON_ARRAY(1)));
- expr = MatchExpressionParser::parse(
- queryArrArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryArrArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
@@ -341,8 +312,7 @@ TEST(MatchExpressionParserSchemaTest, MinLengthFailsToParseNonIntegerArguments)
//
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -355,8 +325,7 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -369,8 +338,7 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -383,8 +351,7 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesDoubleArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxLengthorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -398,80 +365,62 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxLengthFailsToParseNonIntegerArguments) {
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaMaxLength"
<< "abc"));
- auto expr = MatchExpressionParser::parse(
- queryStringArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryEmptyStringArgument = BSON("x" << BSON("$_internalSchemaMaxLength"
<< ""));
- expr = MatchExpressionParser::parse(
- queryEmptyStringArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryEmptyStringArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << 1.5));
- expr = MatchExpressionParser::parse(
- queryDoubleArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << false));
- expr = MatchExpressionParser::parse(
- queryFalseArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
auto queryArrArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << BSON_ARRAY(1)));
- expr = MatchExpressionParser::parse(
- queryArrArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryArrArgument, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondFailsToParseNonObjectArguments) {
auto queryWithInteger = fromjson("{$_internalSchemaCond: [1, {foo: 'bar'}, {baz: 7}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryWithInteger, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryWithInteger, kSimpleCollator).getStatus());
auto queryWithArray = fromjson("{$_internalSchemaCond: [{foo: 'bar'}, [{qux: 3}], {baz: 7}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryWithArray, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryWithArray, kSimpleCollator).getStatus());
auto queryWithString = fromjson("{$_internalSchemaCond: [{foo: 'bar'}, {baz: 7}, 'blah']}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryWithString, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryWithString, kSimpleCollator).getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondFailsToParseIfNotExactlyThreeArguments) {
auto queryNoArguments = fromjson("{$_internalSchemaCond: []}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryNoArguments, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryNoArguments, kSimpleCollator).getStatus());
auto queryOneArgument = fromjson("{$_internalSchemaCond: [{height: 171}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryOneArgument, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryOneArgument, kSimpleCollator).getStatus());
auto queryFourArguments = fromjson(
"{$_internalSchemaCond: [{make: 'lamborghini'}, {model: 'ghost'}, {color: 'celadon'}, "
"{used: false}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(
- queryFourArguments, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus());
+ MatchExpressionParser::parse(queryFourArguments, kSimpleCollator).getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondParsesThreeMatchExpresssions) {
auto query = fromjson(
"{$_internalSchemaCond: [{climate: 'rainy'}, {clothing: 'jacket'}, {clothing: 'shirt'}]}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(
@@ -485,102 +434,79 @@ TEST(MatchExpressionParserSchemaTest, CondParsesThreeMatchExpresssions) {
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseNonObjectArguments) {
auto query = fromjson("{foo: {$_internalSchemaMatchArrayIndex: 7}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson("{foo: {$_internalSchemaMatchArrayIndex: []}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"[{index: 5, namePlaceholder: 'i', expression: {i: 1}}]}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfPlaceholderNotValid) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 5, namePlaceholder: 7, expression: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 5, namePlaceholder: 'Z', expression: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfIndexNotANonnegativeInteger) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 'blah', namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: -1, namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 3.14, namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfExpressionNotValid) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: 'blah'}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {doesntMatchThePlaceholder: 7}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {$invalid: 'blah'}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexParsesSuccessfully) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$lt: 0}}}}}");
- auto matchArrayIndex = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto matchArrayIndex = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(matchArrayIndex.getStatus());
ASSERT_TRUE(matchArrayIndex.getValue()->matchesBSON(fromjson("{foo: [-1, 0, 1]}")));
@@ -591,37 +517,32 @@ TEST(MatchExpressionParserSchemaTest, MatchArrayIndexParsesSuccessfully) {
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithNegativeIndex) {
BSONObj matchPredicate =
fromjson("{$_internalSchemaAllElemMatchFromIndex: [-2, {a: { $lt: 0 }}]}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithNonObjectExpression) {
BSONObj matchPredicate = fromjson("{$_internalSchemaAllElemMatchFromIndex: [-2, 4]}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithInvalidExpression) {
BSONObj matchPredicate =
fromjson("{$_internalSchemaAllElemMatchFromIndex: [-2, {$fakeExpression: 4}]}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithEmptyArray) {
BSONObj matchPredicate = fromjson("{$_internalSchemaAllElemMatchFromIndex: []}");
- auto expr = MatchExpressionParser::parse(
- matchPredicate, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, ParsesCorreclyWithValidInput) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: { $lt: 4 }}]}}");
- auto expr = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: [5, 3, 3, 3, 3, 3]}")));
@@ -630,16 +551,14 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, ParsesCorreclyWithValid
TEST(MatchExpressionParserSchemaTest, InternalTypeFailsToParseOnTypeMismatch) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType" << BSONObj()));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseNumberAlias) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType"
<< "number"));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -650,8 +569,7 @@ TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseNumberAlias) {
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongAlias) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType"
<< "long"));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -662,8 +580,7 @@ TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongAlias) {
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongCode) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType" << 18));
- auto result = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto result = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -676,88 +593,68 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfAFieldIsMis
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: []}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfNamePlaceholderNotAString) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 7, patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: /i/, patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfNamePlaceholderNotValid) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'Capital',"
"patternProperties: [], otherwise: {Capital: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::BadValue);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: '', patternProperties: [], otherwise: {'': 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfPropertiesNotAllStrings) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [7], namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['x', {}], namePlaceholder: 'i',"
"patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -765,18 +662,14 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: ['blah'], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 1}, patternProperties: [{regex: /a/, expression: {i: 0}}, 'blah']}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -784,18 +677,14 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{foo: 1, bar: 1}], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, blah: 0}], otherwise: {i: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest,
@@ -803,26 +692,20 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{expression: {i: 0}}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: 7, expression: {i: 0}}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: 'notARegex', expression: {i: 0}}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -830,18 +713,14 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/, expression: 'blah'}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -849,64 +728,50 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/i, expression: {i: 0}}]}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfMismatchingNamePlaceholders) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {j: 1}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {w: 7}}], otherwise: {i: 'foo'}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfOtherwiseIncorrectType) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: false}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: [{i: 7}]}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfOtherwiseNotAValidExpression) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [], otherwise: {i: {$invalid: 1}}}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::BadValue);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {}}}}}");
- ASSERT_EQ(
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator)
- .getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
+ ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesParsesSuccessfully) {
@@ -914,8 +779,7 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesParsesSuccessfully) {
"{$_internalSchemaAllowedProperties: {properties: ['phoneNumber', 'address'],"
"namePlaceholder: 'i', otherwise: {i: {$gt: 10}},"
"patternProperties: [{regex: /[nN]umber/, expression: {i: {$type: 'number'}}}]}}}");
- auto allowedProperties = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto allowedProperties = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(allowedProperties.getStatus());
ASSERT_TRUE(allowedProperties.getValue()->matchesBSON(
@@ -932,8 +796,7 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesAcceptsEmptyPropertiesAnd
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- auto allowedProperties = MatchExpressionParser::parse(
- query, ExtensionsCallbackDisallowExtensions(), kSimpleCollator);
+ auto allowedProperties = MatchExpressionParser::parse(query, kSimpleCollator);
ASSERT_OK(allowedProperties.getStatus());
ASSERT_TRUE(allowedProperties.getValue()->matchesBSON(BSONObj()));
diff --git a/src/mongo/db/ops/modifier_pull.cpp b/src/mongo/db/ops/modifier_pull.cpp
index f3adc0e3538..bb18a80b723 100644
--- a/src/mongo/db/ops/modifier_pull.cpp
+++ b/src/mongo/db/ops/modifier_pull.cpp
@@ -31,7 +31,6 @@
#include "mongo/base/error_codes.h"
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/update/field_checker.h"
#include "mongo/db/update/log_builder.h"
@@ -123,9 +122,8 @@ Status ModifierPull::init(const BSONElement& modExpr, const Options& opts, bool*
}
// Build the matcher around the object we built above. Currently, we do not allow $pull
- // operations to contain $text/$where clauses, so preserving this behaviour.
- StatusWithMatchExpression parseResult = MatchExpressionParser::parse(
- _exprObj, ExtensionsCallbackDisallowExtensions(), _collator);
+ // operations to contain $text/$where/$geoNear/$near/$nearSphere/$expr clauses.
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(_exprObj, _collator);
if (!parseResult.isOK()) {
return parseResult.getStatus();
}
diff --git a/src/mongo/db/ops/modifier_pull_test.cpp b/src/mongo/db/ops/modifier_pull_test.cpp
index 6d465442dfe..afefb4349ed 100644
--- a/src/mongo/db/ops/modifier_pull_test.cpp
+++ b/src/mongo/db/ops/modifier_pull_test.cpp
@@ -40,17 +40,10 @@
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
+namespace mongo {
+
namespace {
-using mongo::BSONObj;
-using mongo::CollatorInterface;
-using mongo::CollatorInterfaceMock;
-using mongo::LogBuilder;
-using mongo::ModifierInterface;
-using mongo::ModifierPull;
-using mongo::Status;
-using mongo::StringData;
-using mongo::fromjson;
using mongo::mutablebson::Document;
using mongo::mutablebson::Element;
@@ -90,6 +83,62 @@ private:
ModifierPull _mod;
};
+TEST(SimpleMod, InitWithTextFails) {
+ auto update = fromjson("{$pull: {a: {$text: {$search: 'str'}}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(SimpleMod, InitWithWhereFails) {
+ auto update = fromjson("{$pull: {a: {$where: 'this.a == this.b'}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(SimpleMod, InitWithGeoNearElemFails) {
+ auto update =
+ fromjson("{$pull: {a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(SimpleMod, InitWithGeoNearObjectFails) {
+ auto update = fromjson(
+ "{$pull: {a: {b: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(SimpleMod, InitWithExprElemFails) {
+ auto update = fromjson("{$pull: {a: {$expr: 5}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(SimpleMod, InitWithExprObjectFails) {
+ auto update = fromjson("{$pull: {a: {b: {$expr: 5}}}}");
+ const CollatorInterface* collator = nullptr;
+ ModifierPull node;
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
TEST(SimpleMod, PrepareOKTargetNotFound) {
Document doc(fromjson("{}"));
Mod mod(fromjson("{ $pull : { a : { $lt : 1 } } }"));
@@ -712,3 +761,4 @@ TEST(MatchingRegressions, SERVER_3988) {
}
} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/ops/parsed_delete.cpp b/src/mongo/db/ops/parsed_delete.cpp
index 61c3fedf474..8e5d146562e 100644
--- a/src/mongo/db/ops/parsed_delete.cpp
+++ b/src/mongo/db/ops/parsed_delete.cpp
@@ -90,7 +90,14 @@ Status ParsedDelete::parseQueryToCQ() {
qr->setLimit(1);
}
- auto statusWithCQ = CanonicalQuery::canonicalize(_opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(_opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (statusWithCQ.isOK()) {
_canonicalQuery = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index a9bb5658d91..30a2ed15728 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -111,7 +111,14 @@ Status ParsedUpdate::parseQueryToCQ() {
qr->setLimit(1);
}
- auto statusWithCQ = CanonicalQuery::canonicalize(_opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(_opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (statusWithCQ.isOK()) {
_canonicalQuery = std::move(statusWithCQ.getValue());
}
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
index bac942e1f31..efac859eed0 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
@@ -33,7 +33,6 @@
#include "mongo/base/init.h"
#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/pipeline/document.h"
#include "mongo/db/pipeline/document_comparator.h"
#include "mongo/db/pipeline/document_path_support.h"
@@ -544,9 +543,9 @@ intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::createFromBson(
argument.type() == Object);
// We don't need to keep ahold of the MatchExpression, but we do need to ensure that
- // the specified object is parseable.
- auto parsedMatchExpression = MatchExpressionParser::parse(
- argument.embeddedObject(), ExtensionsCallbackDisallowExtensions(), nullptr);
+ // the specified object is parseable and does not contain extensions.
+ auto parsedMatchExpression =
+ MatchExpressionParser::parse(argument.embeddedObject(), nullptr);
uassert(40186,
str::stream()
@@ -554,13 +553,6 @@ intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::createFromBson(
<< parsedMatchExpression.getStatus().reason(),
parsedMatchExpression.isOK());
- uassert(40187,
- str::stream()
- << "Failed to parse 'restrictSearchWithMatch' option to $graphLookup: "
- << "$near not supported.",
- !QueryPlannerCommon::hasNode(parsedMatchExpression.getValue().get(),
- MatchExpression::GEO_NEAR));
-
additionalFilter = argument.embeddedObject().getOwned();
continue;
}
diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp
index 56a51ecd594..5493d21ecd1 100644
--- a/src/mongo/db/pipeline/document_source_match.cpp
+++ b/src/mongo/db/pipeline/document_source_match.cpp
@@ -361,8 +361,13 @@ bool DocumentSourceMatch::isTextQuery(const BSONObj& query) {
void DocumentSourceMatch::joinMatchWith(intrusive_ptr<DocumentSourceMatch> other) {
_predicate = BSON("$and" << BSON_ARRAY(_predicate << other->getQuery()));
- StatusWithMatchExpression status = uassertStatusOK(MatchExpressionParser::parse(
- _predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator(), pExpCtx));
+ StatusWithMatchExpression status = uassertStatusOK(
+ MatchExpressionParser::parse(_predicate,
+ pExpCtx->getCollator(),
+ pExpCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kText |
+ MatchExpressionParser::AllowedFeatures::kExpr));
_expression = std::move(status.getValue());
_dependencies = DepsTracker(_dependencies.getMetadataAvailable());
getDependencies(&_dependencies);
@@ -447,27 +452,8 @@ boost::intrusive_ptr<DocumentSourceMatch> DocumentSourceMatch::descendMatchOnPat
return new DocumentSourceMatch(query.obj(), expCtx);
}
-static void uassertNoDisallowedClauses(BSONObj query) {
- BSONForEach(e, query) {
- // can't use the MatchExpression API because this would segfault the constructor
- uassert(16395,
- "$where is not allowed inside of a $match aggregation expression",
- !str::equals(e.fieldName(), "$where"));
- // geo breaks if it is not the first portion of the pipeline
- uassert(16424,
- "$near is not allowed inside of a $match aggregation expression",
- !str::equals(e.fieldName(), "$near"));
- uassert(16426,
- "$nearSphere is not allowed inside of a $match aggregation expression",
- !str::equals(e.fieldName(), "$nearSphere"));
- if (e.isABSONObj())
- uassertNoDisallowedClauses(e.Obj());
- }
-}
-
intrusive_ptr<DocumentSourceMatch> DocumentSourceMatch::create(
BSONObj filter, const intrusive_ptr<ExpressionContext>& expCtx) {
- uassertNoDisallowedClauses(filter);
intrusive_ptr<DocumentSourceMatch> match(new DocumentSourceMatch(filter, expCtx));
return match;
}
@@ -508,8 +494,13 @@ void DocumentSourceMatch::addDependencies(DepsTracker* deps) const {
DocumentSourceMatch::DocumentSourceMatch(const BSONObj& query,
const intrusive_ptr<ExpressionContext>& pExpCtx)
: DocumentSource(pExpCtx), _predicate(query.getOwned()), _isTextQuery(isTextQuery(query)) {
- StatusWithMatchExpression status = uassertStatusOK(MatchExpressionParser::parse(
- _predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator(), pExpCtx));
+ StatusWithMatchExpression status = uassertStatusOK(
+ MatchExpressionParser::parse(_predicate,
+ pExpCtx->getCollator(),
+ pExpCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatures::kText |
+ MatchExpressionParser::AllowedFeatures::kExpr));
_expression = std::move(status.getValue());
getDependencies(&_dependencies);
diff --git a/src/mongo/db/pipeline/document_source_match_test.cpp b/src/mongo/db/pipeline/document_source_match_test.cpp
index df8a38541aa..c01ae31db9a 100644
--- a/src/mongo/db/pipeline/document_source_match_test.cpp
+++ b/src/mongo/db/pipeline/document_source_match_test.cpp
@@ -33,8 +33,6 @@
#include "mongo/bson/bsonmisc.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/bson/json.h"
-#include "mongo/db/matcher/extensions_callback_noop.h"
-#include "mongo/db/matcher/matcher.h"
#include "mongo/db/pipeline/aggregation_context_fixture.h"
#include "mongo/db/pipeline/document.h"
#include "mongo/db/pipeline/document_source_match.h"
@@ -381,8 +379,8 @@ DEATH_TEST_F(DocumentSourceMatchTest,
"Invariant failure expression::isPathPrefixOf") {
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a.b" << 1 << "b.c" << 1);
- const auto matchExpression = unittest::assertGet(
- MatchExpressionParser::parse(matchSpec, ExtensionsCallbackNoop(), expCtx->getCollator()));
+ const auto matchExpression =
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
}
@@ -391,8 +389,8 @@ DEATH_TEST_F(DocumentSourceMatchTest,
"Invariant failure node->matchType()") {
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a" << BSON("$elemMatch" << BSON("a.b" << 1)));
- const auto matchExpression = unittest::assertGet(
- MatchExpressionParser::parse(matchSpec, ExtensionsCallbackNoop(), expCtx->getCollator()));
+ const auto matchExpression =
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
BSONObjBuilder out;
matchExpression->serialize(&out);
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
@@ -406,16 +404,16 @@ DEATH_TEST_F(DocumentSourceMatchTest,
"Invariant failure") {
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a" << BSON("$elemMatch" << BSON("$gt" << 0)));
- const auto matchExpression = unittest::assertGet(
- MatchExpressionParser::parse(matchSpec, ExtensionsCallbackNoop(), expCtx->getCollator()));
+ const auto matchExpression =
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
}
TEST_F(DocumentSourceMatchTest, ShouldMatchCorrectlyAfterDescendingMatch) {
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a.b" << 1 << "a.c" << 1 << "a.d" << 1);
- const auto matchExpression = unittest::assertGet(
- MatchExpressionParser::parse(matchSpec, ExtensionsCallbackNoop(), expCtx->getCollator()));
+ const auto matchExpression =
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
const auto descendedMatch =
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index ce3fa915f75..2425978a9a0 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -426,7 +426,12 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExe
const ExtensionsCallbackReal extensionsCallback(pExpCtx->opCtx, &nss);
- auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback, pExpCtx);
+ auto cq = CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ pExpCtx,
+ extensionsCallback,
+ MatchExpressionParser::AllowedFeatures::kText |
+ MatchExpressionParser::AllowedFeatures::kExpr);
if (!cq.isOK()) {
// Return an error instead of uasserting, since there are cases where the combination of
diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp
index a8e512c22d9..17d18c6b798 100644
--- a/src/mongo/db/query/canonical_query.cpp
+++ b/src/mongo/db/query/canonical_query.cpp
@@ -98,14 +98,22 @@ bool matchExpressionLessThan(const MatchExpression* lhs, const MatchExpression*
return matchExpressionComparator(lhs, rhs) < 0;
}
+bool parsingCanProduceNoopMatchNodes(const ExtensionsCallback& extensionsCallback,
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) {
+ return extensionsCallback.hasNoopExtensions() &&
+ (allowedFeatures & MatchExpressionParser::AllowedFeatures::kText ||
+ allowedFeatures & MatchExpressionParser::AllowedFeatures::kJavascript);
+}
+
} // namespace
// static
StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
OperationContext* opCtx,
const QueryMessage& qm,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback,
- const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) {
// Make QueryRequest.
auto qrStatus = QueryRequest::fromLegacyQueryMessage(qm);
if (!qrStatus.isOK()) {
@@ -113,15 +121,16 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
}
return CanonicalQuery::canonicalize(
- opCtx, std::move(qrStatus.getValue()), extensionsCallback, expCtx);
+ opCtx, std::move(qrStatus.getValue()), expCtx, extensionsCallback, allowedFeatures);
}
// static
StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
OperationContext* opCtx,
std::unique_ptr<QueryRequest> qr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback,
- const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) {
auto qrStatus = qr->validate();
if (!qrStatus.isOK()) {
return qrStatus;
@@ -138,8 +147,8 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
}
// Make MatchExpression.
- StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(qr->getFilter(), extensionsCallback, collator.get(), expCtx);
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
+ qr->getFilter(), collator.get(), expCtx, extensionsCallback, allowedFeatures);
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
@@ -149,7 +158,10 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery());
Status initStatus =
- cq->init(std::move(qr), extensionsCallback, me.release(), std::move(collator));
+ cq->init(std::move(qr),
+ parsingCanProduceNoopMatchNodes(extensionsCallback, allowedFeatures),
+ me.release(),
+ std::move(collator));
if (!initStatus.isOK()) {
return initStatus;
@@ -159,10 +171,7 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
// static
StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- OperationContext* opCtx,
- const CanonicalQuery& baseQuery,
- MatchExpression* root,
- const ExtensionsCallback& extensionsCallback) {
+ OperationContext* opCtx, const CanonicalQuery& baseQuery, MatchExpression* root) {
// TODO: we should be passing the filter corresponding to 'root' to the QR rather than the base
// query's filter, baseQuery.getQueryRequest().getFilter().
auto qr = stdx::make_unique<QueryRequest>(baseQuery.nss());
@@ -183,8 +192,10 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
// Make the CQ we'll hopefully return.
std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery());
- Status initStatus = cq->init(
- std::move(qr), extensionsCallback, root->shallowClone().release(), std::move(collator));
+ Status initStatus = cq->init(std::move(qr),
+ baseQuery.canHaveNoopMatchNodes(),
+ root->shallowClone().release(),
+ std::move(collator));
if (!initStatus.isOK()) {
return initStatus;
@@ -193,13 +204,13 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
}
Status CanonicalQuery::init(std::unique_ptr<QueryRequest> qr,
- const ExtensionsCallback& extensionsCallback,
+ bool canHaveNoopMatchNodes,
MatchExpression* root,
std::unique_ptr<CollatorInterface> collator) {
_qr = std::move(qr);
_collator = std::move(collator);
- _hasNoopExtensions = extensionsCallback.hasNoopExtensions();
+ _canHaveNoopMatchNodes = canHaveNoopMatchNodes;
_isIsolated = QueryRequest::isQueryIsolated(_qr->getFilter());
// Normalize, sort and validate tree.
@@ -215,8 +226,7 @@ Status CanonicalQuery::init(std::unique_ptr<QueryRequest> qr,
// Validate the projection if there is one.
if (!_qr->getProj().isEmpty()) {
ParsedProjection* pp;
- Status projStatus =
- ParsedProjection::make(_qr->getProj(), _root.get(), &pp, extensionsCallback);
+ Status projStatus = ParsedProjection::make(_qr->getProj(), _root.get(), &pp);
if (!projStatus.isOK()) {
return projStatus;
}
diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h
index f2466fe0c66..54360808233 100644
--- a/src/mongo/db/query/canonical_query.h
+++ b/src/mongo/db/query/canonical_query.h
@@ -33,6 +33,7 @@
#include "mongo/db/dbmessage.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/matcher/expression.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/parsed_projection.h"
#include "mongo/db/query/query_request.h"
@@ -55,8 +56,10 @@ public:
static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
OperationContext* opCtx,
const QueryMessage& qm,
- const ExtensionsCallback& extensionsCallback,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr);
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+ MatchExpressionParser::kBanAllSpecialFeatures);
/**
* If parsing succeeds, returns a std::unique_ptr<CanonicalQuery> representing the parsed
@@ -68,8 +71,10 @@ public:
static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
OperationContext* opCtx,
std::unique_ptr<QueryRequest> qr,
- const ExtensionsCallback&,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr);
+ const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+ MatchExpressionParser::kBanAllSpecialFeatures);
/**
* For testing or for internal clients to use.
@@ -82,11 +87,9 @@ public:
*
* Does not take ownership of 'root'.
*/
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- OperationContext* opCtx,
- const CanonicalQuery& baseQuery,
- MatchExpression* root,
- const ExtensionsCallback& extensionsCallback);
+ static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(OperationContext* opCtx,
+ const CanonicalQuery& baseQuery,
+ MatchExpression* root);
/**
* Returns true if "query" describes an exact-match query on _id, possibly with
@@ -163,14 +166,16 @@ public:
static size_t countNodes(const MatchExpression* root, MatchExpression::MatchType type);
/**
- * Returns true if this canonical query converted extensions such as $where and $text into
- * no-ops during parsing.
+ * Returns true if this canonical query may have converted extensions such as $where and $text
+ * into no-ops during parsing. This will be the case if it allowed $where and $text in parsing,
+ * but parsed using an ExtensionsCallbackNoop. This does not guarantee that a $where or $text
+ * existed in the query.
*
* Queries with a no-op extension context are special because they can be parsed and planned,
* but they cannot be executed.
*/
- bool hasNoopExtensions() const {
- return _hasNoopExtensions;
+ bool canHaveNoopMatchNodes() const {
+ return _canHaveNoopMatchNodes;
}
/**
@@ -186,7 +191,7 @@ private:
CanonicalQuery() {}
Status init(std::unique_ptr<QueryRequest> qr,
- const ExtensionsCallback& extensionsCallback,
+ bool canHaveNoopMatchNodes,
MatchExpression* root,
std::unique_ptr<CollatorInterface> collator);
@@ -199,7 +204,7 @@ private:
std::unique_ptr<CollatorInterface> _collator;
- bool _hasNoopExtensions = false;
+ bool _canHaveNoopMatchNodes = false;
bool _isIsolated;
};
diff --git a/src/mongo/db/query/canonical_query_test.cpp b/src/mongo/db/query/canonical_query_test.cpp
index 542f1ac2477..691079a9560 100644
--- a/src/mongo/db/query/canonical_query_test.cpp
+++ b/src/mongo/db/query/canonical_query_test.cpp
@@ -30,10 +30,10 @@
#include "mongo/client/dbclientinterface.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_factory_interface.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/index_tag.h"
@@ -55,8 +55,13 @@ static const NamespaceString nss("testdb.testcoll");
*/
MatchExpression* parseMatchExpression(const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackNoop(), collator);
+ MatchExpressionParser::parse(obj,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
if (!status.isOK()) {
mongoutils::str::stream ss;
ss << "failed to parse query: " << obj.toString()
@@ -329,8 +334,7 @@ TEST(CanonicalQueryTest, IsValidSortKeyMetaProjection) {
const bool isExplain = false;
auto qr = assertGet(QueryRequest::makeFromFindCommand(
nss, fromjson("{find: 'testcoll', projection: {foo: {$meta: 'sortKey'}}}"), isExplain));
- auto cq = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto cq = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_NOT_OK(cq.getStatus());
}
@@ -341,8 +345,7 @@ TEST(CanonicalQueryTest, IsValidSortKeyMetaProjection) {
nss,
fromjson("{find: 'testcoll', projection: {foo: {$meta: 'sortKey'}}, sort: {bar: 1}}"),
isExplain));
- auto cq = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto cq = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(cq.getStatus());
}
}
@@ -439,8 +442,7 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson(queryStr));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -455,8 +457,7 @@ std::unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setFilter(fromjson(queryStr));
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projStr));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -568,12 +569,10 @@ TEST(CanonicalQueryTest, CanonicalizeFromBaseQuery) {
const std::string cmdStr =
"{find:'bogusns', filter:{$or:[{a:1,b:1},{a:1,c:1}]}, projection:{a:1}, sort:{b:1}}";
auto qr = assertGet(QueryRequest::makeFromFindCommand(nss, fromjson(cmdStr), isExplain));
- auto baseCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto baseCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
MatchExpression* firstClauseExpr = baseCq->root()->getChild(0);
- auto childCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), *baseCq, firstClauseExpr, ExtensionsCallbackDisallowExtensions()));
+ auto childCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), *baseCq, firstClauseExpr));
// Descriptive test. The childCq's filter should be the relevant $or clause, rather than the
// entire query predicate.
@@ -590,8 +589,7 @@ TEST(CanonicalQueryTest, CanonicalQueryFromQRWithNoCollation) {
auto opCtx = serviceContext.makeOperationContext();
auto qr = stdx::make_unique<QueryRequest>(nss);
- auto cq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
ASSERT_TRUE(cq->getCollator() == nullptr);
}
@@ -602,8 +600,7 @@ TEST(CanonicalQueryTest, CanonicalQueryFromQRWithCollation) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setCollation(BSON("locale"
<< "reverse"));
- auto cq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
ASSERT_TRUE(CollatorInterface::collatorsMatch(cq->getCollator(), &collator));
}
@@ -614,11 +611,9 @@ TEST(CanonicalQueryTest, CanonicalQueryFromBaseQueryWithNoCollation) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{$or:[{a:1,b:1},{a:1,c:1}]}"));
- auto baseCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto baseCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
MatchExpression* firstClauseExpr = baseCq->root()->getChild(0);
- auto childCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), *baseCq, firstClauseExpr, ExtensionsCallbackDisallowExtensions()));
+ auto childCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), *baseCq, firstClauseExpr));
ASSERT_TRUE(baseCq->getCollator() == nullptr);
ASSERT_TRUE(childCq->getCollator() == nullptr);
}
@@ -631,11 +626,9 @@ TEST(CanonicalQueryTest, CanonicalQueryFromBaseQueryWithCollation) {
qr->setFilter(fromjson("{$or:[{a:1,b:1},{a:1,c:1}]}"));
qr->setCollation(BSON("locale"
<< "reverse"));
- auto baseCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto baseCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
MatchExpression* firstClauseExpr = baseCq->root()->getChild(0);
- auto childCq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), *baseCq, firstClauseExpr, ExtensionsCallbackDisallowExtensions()));
+ auto childCq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), *baseCq, firstClauseExpr));
ASSERT(baseCq->getCollator());
ASSERT(childCq->getCollator());
ASSERT_TRUE(*(childCq->getCollator()) == *(baseCq->getCollator()));
@@ -647,8 +640,7 @@ TEST(CanonicalQueryTest, SettingCollatorUpdatesCollatorAndMatchExpression) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 'foo', b: {$in: ['bar', 'baz']}}"));
- auto cq = assertGet(CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = assertGet(CanonicalQuery::canonicalize(opCtx.get(), std::move(qr)));
ASSERT_EQUALS(2U, cq->root()->numChildren());
auto firstChild = cq->root()->getChild(0);
auto secondChild = cq->root()->getChild(1);
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index da2a71e2068..ca7fe029325 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -536,8 +536,14 @@ std::string runQuery(OperationContext* opCtx,
beginQueryOp(opCtx, nss, q.query, q.ntoreturn, q.ntoskip);
// Parse the qm into a CanonicalQuery.
-
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, q, ExtensionsCallbackReal(opCtx, &nss));
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ q,
+ expCtx,
+ ExtensionsCallbackReal(opCtx, &nss),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
uasserted(17287,
str::stream() << "Can't canonicalize query: "
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 3f89d4c0148..60d3b166d04 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -55,7 +55,6 @@
#include "mongo/db/exec/update.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index_names.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/matcher/extensions_callback_real.h"
#include "mongo/db/ops/update_lifecycle.h"
@@ -295,7 +294,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx,
// document, so we don't support covered projections. However, we might use the
// simple inclusion fast path.
if (NULL != canonicalQuery->getProj()) {
- ProjectionStageParams params(ExtensionsCallbackReal(opCtx, &collection->ns()));
+ ProjectionStageParams params;
params.projObj = canonicalQuery->getProj()->getProjObj();
params.collator = canonicalQuery->getCollator();
@@ -657,8 +656,7 @@ StatusWith<unique_ptr<PlanStage>> applyProjection(OperationContext* opCtx,
invariant(!proj.isEmpty());
ParsedProjection* rawParsedProj;
- Status ppStatus = ParsedProjection::make(
- proj.getOwned(), cq->root(), &rawParsedProj, ExtensionsCallbackDisallowExtensions());
+ Status ppStatus = ParsedProjection::make(proj.getOwned(), cq->root(), &rawParsedProj);
if (!ppStatus.isOK()) {
return ppStatus;
}
@@ -678,7 +676,7 @@ StatusWith<unique_ptr<PlanStage>> applyProjection(OperationContext* opCtx,
"Cannot use a $meta sortKey projection in findAndModify commands."};
}
- ProjectionStageParams params(ExtensionsCallbackReal(opCtx, &nsString));
+ ProjectionStageParams params;
params.projObj = proj;
params.collator = cq->getCollator();
params.fullExpression = cq->root();
@@ -998,7 +996,14 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorGroup(
const ExtensionsCallbackReal extensionsCallback(opCtx, &nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
}
@@ -1228,12 +1233,16 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCount(
qr->setHint(request.getHint());
qr->setExplain(explain);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ = CanonicalQuery::canonicalize(
opCtx,
std::move(qr),
+ expCtx,
collection ? static_cast<const ExtensionsCallback&>(
ExtensionsCallbackReal(opCtx, &collection->ns()))
- : static_cast<const ExtensionsCallback&>(ExtensionsCallbackNoop()));
+ : static_cast<const ExtensionsCallback&>(ExtensionsCallbackNoop()),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
@@ -1484,7 +1493,14 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDistinct(
auto qr = stdx::make_unique<QueryRequest>(parsedDistinct->getQuery()->getQueryRequest());
qr->setProj(projection);
- auto statusWithCQ = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
}
diff --git a/src/mongo/db/query/get_executor_test.cpp b/src/mongo/db/query/get_executor_test.cpp
index a1dc1f88648..002d4a427b3 100644
--- a/src/mongo/db/query/get_executor_test.cpp
+++ b/src/mongo/db/query/get_executor_test.cpp
@@ -37,7 +37,6 @@
#include "mongo/bson/simple_bsonobj_comparator.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/query_settings.h"
#include "mongo/db/query/query_test_service_context.h"
#include "mongo/stdx/unordered_set.h"
@@ -65,8 +64,7 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setFilter(fromjson(queryStr));
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projStr));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
diff --git a/src/mongo/db/query/index_bounds_builder_test.cpp b/src/mongo/db/query/index_bounds_builder_test.cpp
index 7b400b2c62c..f8bff9d6984 100644
--- a/src/mongo/db/query/index_bounds_builder_test.cpp
+++ b/src/mongo/db/query/index_bounds_builder_test.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/expression_index.h"
#include "mongo/unittest/unittest.h"
@@ -60,8 +59,7 @@ double NaN = numeric_limits<double>::quiet_NaN();
*/
MatchExpression* parseMatchExpression(const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
ASSERT_TRUE(status.isOK());
MatchExpression* expr(status.getValue().release());
return expr;
diff --git a/src/mongo/db/query/parsed_distinct.cpp b/src/mongo/db/query/parsed_distinct.cpp
index 8b024533326..da071756726 100644
--- a/src/mongo/db/query/parsed_distinct.cpp
+++ b/src/mongo/db/query/parsed_distinct.cpp
@@ -201,7 +201,13 @@ StatusWith<ParsedDistinct> ParsedDistinct::parse(OperationContext* opCtx,
qr->setExplain(isExplain);
- auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto cq = CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ extensionsCallback,
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!cq.isOK()) {
return cq.getStatus();
}
diff --git a/src/mongo/db/query/parsed_distinct_test.cpp b/src/mongo/db/query/parsed_distinct_test.cpp
index 68554d2637c..f751534cca4 100644
--- a/src/mongo/db/query/parsed_distinct_test.cpp
+++ b/src/mongo/db/query/parsed_distinct_test.cpp
@@ -31,7 +31,7 @@
#include <algorithm>
#include "mongo/bson/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/aggregation_request.h"
#include "mongo/db/query/parsed_distinct.h"
#include "mongo/db/query/query_test_service_context.h"
@@ -51,7 +51,7 @@ TEST(ParsedDistinctTest, ConvertToAggregationNoQuery) {
auto pd = ParsedDistinct::parse(opCtx,
testns,
fromjson("{distinct: 'testcoll', key: 'x'}"),
- ExtensionsCallbackDisallowExtensions(),
+ ExtensionsCallbackNoop(),
!isExplain);
ASSERT_OK(pd.getStatus());
@@ -109,7 +109,7 @@ TEST(ParsedDistinctTest, ConvertToAggregationWithAllOptions) {
<< "aComment"
<< "maxTimeMS"
<< 100),
- ExtensionsCallbackDisallowExtensions(),
+ ExtensionsCallbackNoop(),
!isExplain);
ASSERT_OK(pd.getStatus());
@@ -155,7 +155,7 @@ TEST(ParsedDistinctTest, ConvertToAggregationWithQuery) {
auto pd = ParsedDistinct::parse(opCtx,
testns,
fromjson("{distinct: 'testcoll', key: 'y', query: {z: 7}}"),
- ExtensionsCallbackDisallowExtensions(),
+ ExtensionsCallbackNoop(),
!isExplain);
ASSERT_OK(pd.getStatus());
@@ -196,7 +196,7 @@ TEST(ParsedDistinctTest, ExplainNotIncludedWhenConvertingToAggregationCommand) {
auto pd = ParsedDistinct::parse(opCtx,
testns,
fromjson("{distinct: 'testcoll', key: 'x'}"),
- ExtensionsCallbackDisallowExtensions(),
+ ExtensionsCallbackNoop(),
isExplain);
ASSERT_OK(pd.getStatus());
diff --git a/src/mongo/db/query/parsed_projection.cpp b/src/mongo/db/query/parsed_projection.cpp
index d83b9e786ee..575c5d5dff5 100644
--- a/src/mongo/db/query/parsed_projection.cpp
+++ b/src/mongo/db/query/parsed_projection.cpp
@@ -28,9 +28,8 @@
#include "mongo/db/query/parsed_projection.h"
-#include "mongo/db/query/query_request.h"
-
#include "mongo/bson/simple_bsonobj_comparator.h"
+#include "mongo/db/query/query_request.h"
namespace mongo {
@@ -49,8 +48,7 @@ using std::string;
// static
Status ParsedProjection::make(const BSONObj& spec,
const MatchExpression* const query,
- ParsedProjection** out,
- const ExtensionsCallback& extensionsCallback) {
+ ParsedProjection** out) {
// Whether we're including or excluding fields.
enum class IncludeExclude { kUninitialized, kInclude, kExclude };
IncludeExclude includeExclude = IncludeExclude::kUninitialized;
@@ -128,10 +126,11 @@ Status ParsedProjection::make(const BSONObj& spec,
// is ok because the parsed MatchExpression is not used after being created. We are
// only parsing here in order to ensure that the elemMatch projection is valid.
//
- // TODO: Is there a faster way of validating the elemMatchObj?
+ // Match expression extensions such as $text, $where, $geoNear, $near, $nearSphere,
+ // and $expr are not allowed in $elemMatch projections.
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(elemMatchObj, extensionsCallback, collator);
+ MatchExpressionParser::parse(elemMatchObj, collator);
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
diff --git a/src/mongo/db/query/parsed_projection.h b/src/mongo/db/query/parsed_projection.h
index 0730f39c18c..2f273c5d303 100644
--- a/src/mongo/db/query/parsed_projection.h
+++ b/src/mongo/db/query/parsed_projection.h
@@ -47,8 +47,7 @@ public:
*/
static Status make(const BSONObj& spec,
const MatchExpression* const query,
- ParsedProjection** out,
- const ExtensionsCallback& extensionsCallback);
+ ParsedProjection** out);
/**
* Returns true if the projection requires match details from the query,
diff --git a/src/mongo/db/query/parsed_projection_test.cpp b/src/mongo/db/query/parsed_projection_test.cpp
index fa17165932d..22046f8b531 100644
--- a/src/mongo/db/query/parsed_projection_test.cpp
+++ b/src/mongo/db/query/parsed_projection_test.cpp
@@ -31,7 +31,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_always_boolean.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/unittest/unittest.h"
#include <memory>
@@ -49,13 +48,11 @@ using namespace mongo;
unique_ptr<ParsedProjection> createParsedProjection(const BSONObj& query, const BSONObj& projObj) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(query, collator);
ASSERT(statusWithMatcher.isOK());
std::unique_ptr<MatchExpression> queryMatchExpr = std::move(statusWithMatcher.getValue());
ParsedProjection* out = NULL;
- Status status = ParsedProjection::make(
- projObj, queryMatchExpr.get(), &out, ExtensionsCallbackDisallowExtensions());
+ Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
if (!status.isOK()) {
FAIL(mongoutils::str::stream() << "failed to parse projection " << projObj << " (query: "
<< query
@@ -80,13 +77,11 @@ void assertInvalidProjection(const char* queryStr, const char* projStr) {
BSONObj query = fromjson(queryStr);
BSONObj projObj = fromjson(projStr);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(query, collator);
ASSERT(statusWithMatcher.isOK());
std::unique_ptr<MatchExpression> queryMatchExpr = std::move(statusWithMatcher.getValue());
ParsedProjection* out = NULL;
- Status status = ParsedProjection::make(
- projObj, queryMatchExpr.get(), &out, ExtensionsCallbackDisallowExtensions());
+ Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
std::unique_ptr<ParsedProjection> destroy(out);
ASSERT(!status.isOK());
}
@@ -163,6 +158,24 @@ TEST(ParsedProjectionTest, InvalidPositionalOperatorProjections) {
assertInvalidProjection("{a: [1, 2, 3]}", "{'.$': 1}");
}
+TEST(ParsedProjectionTest, InvalidElemMatchTextProjection) {
+ assertInvalidProjection("{}", "{a: {$elemMatch: {$text: {$search: 'str'}}}}");
+}
+
+TEST(ParsedProjectionTest, InvalidElemMatchWhereProjection) {
+ assertInvalidProjection("{}", "{a: {$elemMatch: {$where: 'this.a == this.b'}}}");
+}
+
+TEST(ParsedProjectionTest, InvalidElemMatchGeoNearProjection) {
+ assertInvalidProjection(
+ "{}",
+ "{a: {$elemMatch: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}");
+}
+
+TEST(ParsedProjectionTest, InvalidElemMatchExprProjection) {
+ assertInvalidProjection("{}", "{a: {$elemMatch: {$expr: 5}}}");
+}
+
TEST(ParsedProjectionTest, ValidPositionalOperatorProjections) {
createParsedProjection("{a: 1}", "{'a.$': 1}");
createParsedProjection("{a: 1}", "{'a.foo.bar.$': 1}");
@@ -191,15 +204,13 @@ TEST(ParsedProjectionTest, InvalidPositionalProjectionDefaultPathMatchExpression
ParsedProjection* out = NULL;
BSONObj projObj = fromjson("{'a.$': 1}");
- Status status = ParsedProjection::make(
- projObj, queryMatchExpr.get(), &out, ExtensionsCallbackDisallowExtensions());
+ Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
ASSERT(!status.isOK());
std::unique_ptr<ParsedProjection> destroy(out);
// Projecting onto empty field should fail.
BSONObj emptyFieldProjObj = fromjson("{'.$': 1}");
- status = ParsedProjection::make(
- emptyFieldProjObj, queryMatchExpr.get(), &out, ExtensionsCallbackDisallowExtensions());
+ status = ParsedProjection::make(emptyFieldProjObj, queryMatchExpr.get(), &out);
ASSERT(!status.isOK());
}
diff --git a/src/mongo/db/query/plan_cache_indexability_test.cpp b/src/mongo/db/query/plan_cache_indexability_test.cpp
index 3cc90e3429a..11635c4b665 100644
--- a/src/mongo/db/query/plan_cache_indexability_test.cpp
+++ b/src/mongo/db/query/plan_cache_indexability_test.cpp
@@ -30,7 +30,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/index_entry.h"
#include "mongo/db/query/plan_cache_indexability.h"
@@ -41,8 +40,7 @@ namespace {
std::unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj,
const CollatorInterface* collator = nullptr) {
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
if (!status.isOK()) {
FAIL(str::stream() << "failed to parse query: " << obj.toString() << ". Reason: "
<< status.getStatus().toString());
diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp
index dd5eead802c..b94ab624fe1 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -38,7 +38,8 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
+#include "mongo/db/matcher/extensions_callback_noop.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/plan_ranker.h"
#include "mongo/db/query/query_knobs.h"
@@ -72,8 +73,13 @@ unique_ptr<CanonicalQuery> canonicalize(const BSONObj& queryObj) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(queryObj);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -95,8 +101,13 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projStr));
qr->setCollation(fromjson(collationStr));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -125,8 +136,13 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setHint(fromjson(hintStr));
qr->setMin(fromjson(minStr));
qr->setMax(fromjson(maxStr));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -159,8 +175,13 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setMax(fromjson(maxStr));
qr->setSnapshot(snapshot);
qr->setExplain(explain);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
@@ -170,8 +191,13 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ MatchExpressionParser::parse(obj,
+ collator,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
if (!status.isOK()) {
str::stream ss;
ss << "failed to parse query: " << obj.toString()
@@ -563,8 +589,13 @@ protected:
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
Status s = QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns);
ASSERT_OK(s);
@@ -585,8 +616,13 @@ protected:
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
Status s = QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns);
ASSERT_OK(s);
@@ -666,8 +702,13 @@ protected:
qr->setSort(sort);
qr->setProj(proj);
qr->setCollation(collation);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/db/query/planner_ixselect_test.cpp b/src/mongo/db/query/planner_ixselect_test.cpp
index 1c273db8716..bacd8990a56 100644
--- a/src/mongo/db/query/planner_ixselect_test.cpp
+++ b/src/mongo/db/query/planner_ixselect_test.cpp
@@ -34,7 +34,6 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/index_tag.h"
#include "mongo/unittest/unittest.h"
@@ -54,8 +53,7 @@ using std::vector;
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
ASSERT_TRUE(status.isOK());
return std::move(status.getValue());
}
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 17e6bb09daa..1fcc20df418 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_always_boolean.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_planner_test_fixture.h"
@@ -4268,8 +4267,7 @@ TEST_F(QueryPlannerTest, CacheDataFromTaggedTreeFailsOnBadInput) {
auto qr = stdx::make_unique<QueryRequest>(NamespaceString("test.collection"));
qr->setFilter(BSON("a" << 3));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
scopedCq->root()->setTag(new IndexTag(1));
@@ -4284,8 +4282,7 @@ TEST_F(QueryPlannerTest, TagAccordingToCacheFailsOnBadInput) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 3));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
@@ -4314,8 +4311,7 @@ TEST_F(QueryPlannerTest, TagAccordingToCacheFailsOnBadInput) {
// Regenerate canonical query in order to clear tags.
auto newQR = stdx::make_unique<QueryRequest>(nss);
newQR->setFilter(BSON("a" << 3));
- statusWithCQ = CanonicalQuery::canonicalize(
- opCtx.get(), std::move(newQR), ExtensionsCallbackDisallowExtensions());
+ statusWithCQ = CanonicalQuery::canonicalize(opCtx.get(), std::move(newQR));
ASSERT_OK(statusWithCQ.getStatus());
scopedCq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/db/query/query_planner_test_fixture.cpp b/src/mongo/db/query/query_planner_test_fixture.cpp
index 3376d24eb04..ae04eec22a4 100644
--- a/src/mongo/db/query/query_planner_test_fixture.cpp
+++ b/src/mongo/db/query/query_planner_test_fixture.cpp
@@ -35,9 +35,9 @@
#include <algorithm>
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/query_knobs.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_planner_test_lib.h"
@@ -249,8 +249,13 @@ void QueryPlannerTest::runQueryFull(const BSONObj& query,
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx.get(), std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
cq = std::move(statusWithCQ.getValue());
@@ -328,8 +333,13 @@ void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx.get(), std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
cq = std::move(statusWithCQ.getValue());
@@ -349,8 +359,13 @@ void QueryPlannerTest::runQueryAsCommand(const BSONObj& cmdObj) {
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx.get(), std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
cq = std::move(statusWithCQ.getValue());
@@ -370,8 +385,13 @@ void QueryPlannerTest::runInvalidQueryAsCommand(const BSONObj& cmdObj) {
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx.get(), std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx.get(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_OK(statusWithCQ.getStatus());
cq = std::move(statusWithCQ.getValue());
@@ -452,8 +472,7 @@ void QueryPlannerTest::assertHasOneSolutionOf(const std::vector<std::string>& so
std::unique_ptr<MatchExpression> QueryPlannerTest::parseMatchExpression(
const BSONObj& obj, const CollatorInterface* collator) {
- StatusWithMatchExpression status =
- MatchExpressionParser::parse(obj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
if (!status.isOK()) {
FAIL(str::stream() << "failed to parse query: " << obj.toString() << ". Reason: "
<< status.getStatus().toString());
diff --git a/src/mongo/db/query/query_planner_test_lib.cpp b/src/mongo/db/query/query_planner_test_lib.cpp
index bd647280d3a..c1920f821d0 100644
--- a/src/mongo/db/query/query_planner_test_lib.cpp
+++ b/src/mongo/db/query/query_planner_test_lib.cpp
@@ -36,7 +36,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_factory_mock.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_solution.h"
@@ -67,8 +66,8 @@ bool filterMatches(const BSONObj& testFilter,
testCollator = std::move(collator.getValue());
}
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- testFilter, ExtensionsCallbackDisallowExtensions(), testCollator.get());
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(testFilter, testCollator.get());
if (!statusWithMatcher.isOK()) {
return false;
}
diff --git a/src/mongo/db/query/query_solution_test.cpp b/src/mongo/db/query/query_solution_test.cpp
index a3a76deaa43..821b1efd4e9 100644
--- a/src/mongo/db/query/query_solution_test.cpp
+++ b/src/mongo/db/query/query_solution_test.cpp
@@ -30,7 +30,6 @@
#include "mongo/bson/bsontypes.h"
#include "mongo/bson/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/index_bounds_builder.h"
#include "mongo/db/query/index_entry.h"
@@ -687,12 +686,10 @@ TEST(QuerySolutionTest, IndexScanNodeHasFieldExcludesSimpleBoundsStringFieldWhen
std::unique_ptr<ParsedProjection> createParsedProjection(const BSONObj& query,
const BSONObj& projObj) {
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression queryMatchExpr =
- MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression queryMatchExpr = MatchExpressionParser::parse(query, collator);
ASSERT(queryMatchExpr.isOK());
ParsedProjection* out = nullptr;
- Status status = ParsedProjection::make(
- projObj, queryMatchExpr.getValue().get(), &out, ExtensionsCallbackDisallowExtensions());
+ Status status = ParsedProjection::make(projObj, queryMatchExpr.getValue().get(), &out);
if (!status.isOK()) {
FAIL(mongoutils::str::stream() << "failed to parse projection " << projObj << " (query: "
<< query
diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp
index 96fc04c3499..1319ac07f52 100644
--- a/src/mongo/db/query/stage_builder.cpp
+++ b/src/mongo/db/query/stage_builder.cpp
@@ -140,7 +140,7 @@ PlanStage* buildStages(OperationContext* opCtx,
return nullptr;
}
- ProjectionStageParams params(ExtensionsCallbackReal(opCtx, &collection->ns()));
+ ProjectionStageParams params;
params.projObj = pn->projection;
params.collator = cq.getCollator();
@@ -390,7 +390,7 @@ bool StageBuilder::build(OperationContext* opCtx,
// queries that disallow extensions, can be properly executed. If the query does not have
// $text/$where context (and $text/$where are allowed), then no attempt should be made to
// execute the query.
- invariant(!cq.hasNoopExtensions());
+ invariant(!cq.canHaveNoopMatchNodes());
if (nullptr == wsIn || nullptr == rootOut) {
return false;
diff --git a/src/mongo/db/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp
index c4d05d660fd..b6d4e3a2c2a 100644
--- a/src/mongo/db/repl/apply_ops.cpp
+++ b/src/mongo/db/repl/apply_ops.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/db_raii.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/index/index_descriptor.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/operation_context.h"
@@ -269,10 +268,9 @@ Status _checkPrecondition(OperationContext* opCtx,
}
const CollatorInterface* collator = collection->getDefaultCollator();
- // Apply-ops would never have a $where/$text matcher. Using the "DisallowExtensions"
- // callback ensures that parsing will throw an error if $where or $text are found.
- Matcher matcher(
- preCondition["res"].Obj(), ExtensionsCallbackDisallowExtensions(), collator);
+ // applyOps does not allow any extensions, such as $text, $where, $geoNear, $near,
+ // $nearSphere, or $expr.
+ Matcher matcher(preCondition["res"].Obj(), collator);
if (!matcher.matches(realres)) {
result->append("got", realres);
result->append("whatFailed", preCondition);
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 24f00dfff4c..8f4bb4ae246 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -49,7 +49,6 @@
#include "mongo/db/db_raii.h"
#include "mongo/db/exec/delete.h"
#include "mongo/db/index/index_descriptor.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/ops/insert.h"
#include "mongo/db/query/internal_plans.h"
@@ -243,8 +242,7 @@ private:
BSON(keyFieldName << BSON("$gte" << kDawnOfTime << "$lte" << expirationTime));
auto qr = stdx::make_unique<QueryRequest>(collectionNSS);
qr->setFilter(query);
- auto canonicalQuery = CanonicalQuery::canonicalize(
- opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto canonicalQuery = CanonicalQuery::canonicalize(opCtx, std::move(qr));
invariantOK(canonicalQuery.getStatus());
DeleteStageParams params;
diff --git a/src/mongo/db/update/path_support_test.cpp b/src/mongo/db/update/path_support_test.cpp
index 339781699e1..3de5e8eff00 100644
--- a/src/mongo/db/update/path_support_test.cpp
+++ b/src/mongo/db/update/path_support_test.cpp
@@ -48,7 +48,6 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/mongoutils/str.h"
@@ -590,9 +589,7 @@ TEST_F(ArrayDoc, CreatePathAtFailsIfElemFoundIsArrayAndIdxFoundFieldIsNonNumeric
static MatchExpression* makeExpr(const BSONObj& exprBSON) {
const CollatorInterface* collator = nullptr;
- return MatchExpressionParser::parse(exprBSON, ExtensionsCallbackDisallowExtensions(), collator)
- .getValue()
- .release();
+ return MatchExpressionParser::parse(exprBSON, collator).getValue().release();
}
static void assertContains(const EqualityMatches& equalities, const BSONObj& wrapped) {
diff --git a/src/mongo/db/update/pull_node.cpp b/src/mongo/db/update/pull_node.cpp
index 5842718c388..9ef4e02724b 100644
--- a/src/mongo/db/update/pull_node.cpp
+++ b/src/mongo/db/update/pull_node.cpp
@@ -31,7 +31,6 @@
#include "mongo/db/update/pull_node.h"
#include "mongo/db/matcher/copyable_match_expression.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface.h"
namespace mongo {
@@ -43,9 +42,7 @@ namespace mongo {
class PullNode::ObjectMatcher final : public PullNode::ElementMatcher {
public:
ObjectMatcher(BSONObj matchCondition, const CollatorInterface* collator)
- : _matchExpr(
- matchCondition, stdx::make_unique<ExtensionsCallbackDisallowExtensions>(), collator) {
- }
+ : _matchExpr(matchCondition, collator) {}
std::unique_ptr<ElementMatcher> clone() const final {
return stdx::make_unique<ObjectMatcher>(*this);
@@ -77,9 +74,7 @@ private:
class PullNode::WrappedObjectMatcher final : public PullNode::ElementMatcher {
public:
WrappedObjectMatcher(BSONElement matchCondition, const CollatorInterface* collator)
- : _matchExpr(matchCondition.wrap(""),
- stdx::make_unique<ExtensionsCallbackDisallowExtensions>(),
- collator) {}
+ : _matchExpr(matchCondition.wrap(""), collator) {}
std::unique_ptr<ElementMatcher> clone() const final {
return stdx::make_unique<WrappedObjectMatcher>(*this);
diff --git a/src/mongo/db/update/pull_node_test.cpp b/src/mongo/db/update/pull_node_test.cpp
index d54640c0d1a..0fa4c83dcc0 100644
--- a/src/mongo/db/update/pull_node_test.cpp
+++ b/src/mongo/db/update/pull_node_test.cpp
@@ -63,6 +63,62 @@ TEST(PullNodeTest, InitWithBadTopLevelOperatorFails) {
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
+TEST(PullNodeTest, InitWithTextFails) {
+ auto update = fromjson("{$pull: {a: {$text: {$search: 'str'}}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(PullNodeTest, InitWithWhereFails) {
+ auto update = fromjson("{$pull: {a: {$where: 'this.a == this.b'}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(PullNodeTest, InitWithGeoNearElemFails) {
+ auto update =
+ fromjson("{$pull: {a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(PullNodeTest, InitWithGeoNearObjectFails) {
+ auto update = fromjson(
+ "{$pull: {a: {b: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(PullNodeTest, InitWithExprElemFails) {
+ auto update = fromjson("{$pull: {a: {$expr: 5}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
+TEST(PullNodeTest, InitWithExprObjectFails) {
+ auto update = fromjson("{$pull: {a: {b: {$expr: 5}}}}");
+ const CollatorInterface* collator = nullptr;
+ PullNode node;
+ auto status = node.init(update["$pull"]["a"], collator);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQUALS(ErrorCodes::BadValue, status);
+}
+
TEST_F(PullNodeTest, TargetNotFound) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
const CollatorInterface* collator = nullptr;
@@ -361,6 +417,62 @@ TEST_F(PullNodeTest, ApplyStringMatchAfterSetCollator) {
ASSERT_FALSE(doc2.isInPlaceModeEnabled());
}
+TEST_F(PullNodeTest, ApplyElementMatchAfterSetCollator) {
+ auto update = fromjson("{$pull : {a: {$gte: 'c'}}}");
+ PullNode node;
+ const CollatorInterface* collator = nullptr;
+ ASSERT_OK(node.init(update["$pull"]["a"], collator));
+
+ // First without a collator.
+ mutablebson::Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }"));
+ setPathTaken("a");
+ auto result = node.apply(getApplyParams(doc.root()["a"]));
+ ASSERT_FALSE(result.noop);
+ ASSERT_FALSE(result.indexesAffected);
+ ASSERT_EQUALS(fromjson("{a: ['a', 'b']}"), doc);
+ ASSERT_FALSE(doc.isInPlaceModeEnabled());
+
+ // Now with a collator.
+ CollatorInterfaceMock mockCollator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ node.setCollator(&mockCollator);
+ mutablebson::Document doc2(fromjson("{ a : ['a', 'b', 'c', 'd'] }"));
+ resetApplyParams();
+ setPathTaken("a");
+ result = node.apply(getApplyParams(doc2.root()["a"]));
+ ASSERT_FALSE(result.noop);
+ ASSERT_FALSE(result.indexesAffected);
+ ASSERT_EQUALS(fromjson("{a: []}"), doc2);
+ ASSERT_FALSE(doc2.isInPlaceModeEnabled());
+}
+
+TEST_F(PullNodeTest, ApplyObjectMatchAfterSetCollator) {
+ auto update = fromjson("{$pull : {a: {b: 'y'}}}");
+ PullNode node;
+ const CollatorInterface* collator = nullptr;
+ ASSERT_OK(node.init(update["$pull"]["a"], collator));
+
+ // First without a collator.
+ mutablebson::Document doc(fromjson("{a : [{b: 'w'}, {b: 'x'}, {b: 'y'}, {b: 'z'}]}"));
+ setPathTaken("a");
+ auto result = node.apply(getApplyParams(doc.root()["a"]));
+ ASSERT_FALSE(result.noop);
+ ASSERT_FALSE(result.indexesAffected);
+ ASSERT_EQUALS(fromjson("{a : [{b: 'w'}, {b: 'x'}, {b: 'z'}]}"), doc);
+ ASSERT_FALSE(doc.isInPlaceModeEnabled());
+
+ // Now with a collator.
+ CollatorInterfaceMock mockCollator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ node.setCollator(&mockCollator);
+ mutablebson::Document doc2(fromjson("{a : [{b: 'w'}, {b: 'x'}, {b: 'y'}, {b: 'z'}]}"));
+ resetApplyParams();
+ setPathTaken("a");
+ result = node.apply(getApplyParams(doc2.root()["a"]));
+ ASSERT_FALSE(result.noop);
+ ASSERT_FALSE(result.indexesAffected);
+ ASSERT_EQUALS(fromjson("{a: []}"), doc2);
+ ASSERT_FALSE(doc2.isInPlaceModeEnabled());
+}
+
TEST_F(PullNodeTest, SetCollatorDoesNotAffectClone) {
auto update = fromjson("{$pull : {a: 'c'}}");
PullNode node;
diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp
index 6d1d89e7f77..52700a13f80 100644
--- a/src/mongo/db/update/update_driver.cpp
+++ b/src/mongo/db/update/update_driver.cpp
@@ -214,8 +214,14 @@ Status UpdateDriver::populateDocumentWithQueryFields(OperationContext* opCtx,
// $where/$text clauses do not make sense, hence empty ExtensionsCallback.
auto qr = stdx::make_unique<QueryRequest>(NamespaceString(""));
qr->setFilter(query);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return statusWithCQ.getStatus();
}
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 1db6048e282..4af64c6be73 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -36,7 +36,6 @@
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/exec/multi_plan.h"
#include "mongo/db/exec/plan_stage.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/pipeline/dependencies.h"
#include "mongo/db/pipeline/document_source.h"
#include "mongo/db/pipeline/document_source_cursor.h"
@@ -101,8 +100,7 @@ protected:
if (hint) {
qr->setHint(*hint);
}
- auto cq = uassertStatusOK(CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = uassertStatusOK(CanonicalQuery::canonicalize(&_opCtx, std::move(qr)));
auto exec = uassertStatusOK(
getExecutor(&_opCtx, ctx.getCollection(), std::move(cq), PlanExecutor::NO_YIELD));
diff --git a/src/mongo/dbtests/executor_registry.cpp b/src/mongo/dbtests/executor_registry.cpp
index 46ec9c1e3a0..8d961c51eff 100644
--- a/src/mongo/dbtests/executor_registry.cpp
+++ b/src/mongo/dbtests/executor_registry.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/db/service_context.h"
#include "mongo/dbtests/dbtests.h"
@@ -78,8 +77,7 @@ public:
// Create a plan executor to hold it
auto qr = stdx::make_unique<QueryRequest>(nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/dbtests/matchertests.cpp b/src/mongo/dbtests/matchertests.cpp
index 095df864a1e..3d20d60fde3 100644
--- a/src/mongo/dbtests/matchertests.cpp
+++ b/src/mongo/dbtests/matchertests.cpp
@@ -36,9 +36,9 @@
#include "mongo/db/client.h"
#include "mongo/db/db_raii.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_real.h"
#include "mongo/db/matcher/matcher.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/util/timer.h"
@@ -62,7 +62,7 @@ public:
void run() {
BSONObj query = fromjson("{\"a\":\"b\"}");
const CollatorInterface* collator = nullptr;
- M m(query, ExtensionsCallbackDisallowExtensions(), collator);
+ M m(query, collator);
ASSERT(m.matches(fromjson("{\"a\":\"b\"}")));
}
};
@@ -73,7 +73,7 @@ public:
void run() {
BSONObj query = fromjson("{\"a\":5}");
const CollatorInterface* collator = nullptr;
- M m(query, ExtensionsCallbackDisallowExtensions(), collator);
+ M m(query, collator);
ASSERT(m.matches(fromjson("{\"a\":5}")));
}
};
@@ -85,7 +85,7 @@ public:
BSONObjBuilder query;
query.append("a", 5);
const CollatorInterface* collator = nullptr;
- M m(query.done(), ExtensionsCallbackDisallowExtensions(), collator);
+ M m(query.done(), collator);
ASSERT(m.matches(fromjson("{\"a\":5}")));
}
};
@@ -96,7 +96,7 @@ public:
void run() {
BSONObj query = fromjson("{\"a\":{\"$gt\":4}}");
const CollatorInterface* collator = nullptr;
- M m(query, ExtensionsCallbackDisallowExtensions(), collator);
+ M m(query, collator);
BSONObjBuilder b;
b.append("a", 5);
ASSERT(m.matches(b.done()));
@@ -112,7 +112,7 @@ public:
ASSERT_EQUALS(NumberInt, query["a"].embeddedObject()["$in"].embeddedObject()["0"].type());
const CollatorInterface* collator = nullptr;
- M m(query, ExtensionsCallbackDisallowExtensions(), collator);
+ M m(query, collator);
{
BSONObjBuilder b;
@@ -140,7 +140,7 @@ class MixedNumericEmbedded {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M m(BSON("a" << BSON("x" << 1)), ExtensionsCallbackDisallowExtensions(), collator);
+ M m(BSON("a" << BSON("x" << 1)), collator);
ASSERT(m.matches(BSON("a" << BSON("x" << 1))));
ASSERT(m.matches(BSON("a" << BSON("x" << 1.0))));
}
@@ -151,7 +151,7 @@ class Size {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M m(fromjson("{a:{$size:4}}"), ExtensionsCallbackDisallowExtensions(), collator);
+ M m(fromjson("{a:{$size:4}}"), collator);
ASSERT(m.matches(fromjson("{a:[1,2,3,4]}")));
ASSERT(!m.matches(fromjson("{a:[1,2,3]}")));
ASSERT(!m.matches(fromjson("{a:[1,2,3,'a','b']}")));
@@ -164,9 +164,7 @@ class WithinBox {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M m(fromjson("{loc:{$within:{$box:[{x: 4, y:4},[6,6]]}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
+ M m(fromjson("{loc:{$within:{$box:[{x: 4, y:4},[6,6]]}}}"), collator);
ASSERT(!m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: [4,4]}")));
ASSERT(m.matches(fromjson("{loc: [5,5]}")));
@@ -180,9 +178,7 @@ class WithinPolygon {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M m(fromjson("{loc:{$within:{$polygon:[{x:0,y:0},[0,5],[5,5],[5,0]]}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
+ M m(fromjson("{loc:{$within:{$polygon:[{x:0,y:0},[0,5],[5,5],[5,0]]}}}"), collator);
ASSERT(m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: [4,4]}")));
ASSERT(m.matches(fromjson("{loc: {x:5,y:5}}")));
@@ -196,9 +192,7 @@ class WithinCenter {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M m(fromjson("{loc:{$within:{$center:[{x:30,y:30},10]}}}"),
- ExtensionsCallbackDisallowExtensions(),
- collator);
+ M m(fromjson("{loc:{$within:{$center:[{x:30,y:30},10]}}}"), collator);
ASSERT(!m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: {x:30,y:30}}")));
ASSERT(m.matches(fromjson("{loc: [20,30]}")));
@@ -215,7 +209,7 @@ class ElemMatchKey {
public:
void run() {
const CollatorInterface* collator = nullptr;
- M matcher(BSON("a.b" << 1), ExtensionsCallbackDisallowExtensions(), collator);
+ M matcher(BSON("a.b" << 1), collator);
MatchDetails details;
details.requestElemMatchKey();
ASSERT(!details.hasElemMatchKey());
@@ -236,10 +230,13 @@ public:
AutoGetCollectionForReadCommand ctx(&opCtx, nss);
const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
M m(BSON("$where"
<< "function(){ return this.a == 1; }"),
+ collator,
+ expCtx,
ExtensionsCallbackReal(&opCtx, &nss),
- collator);
+ MatchExpressionParser::AllowedFeatures::kJavascript);
ASSERT(m.matches(BSON("a" << 1)));
ASSERT(!m.matches(BSON("a" << 2)));
}
@@ -250,7 +247,7 @@ class TimingBase {
public:
long dotime(const BSONObj& patt, const BSONObj& obj) {
const CollatorInterface* collator = nullptr;
- M m(patt, ExtensionsCallbackDisallowExtensions(), collator);
+ M m(patt, collator);
Timer t;
for (int i = 0; i < 900000; i++) {
if (!m.matches(obj)) {
@@ -283,7 +280,6 @@ public:
const CollatorInterface* collator = nullptr;
M matcher(BSON("a"
<< "string"),
- ExtensionsCallbackDisallowExtensions(),
collator);
ASSERT(!matcher.matches(BSON("a"
<< "string2")));
@@ -298,7 +294,6 @@ public:
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
M matcher(BSON("a"
<< "string"),
- ExtensionsCallbackDisallowExtensions(),
&collator);
ASSERT(matcher.matches(BSON("a"
<< "string2")));
diff --git a/src/mongo/dbtests/oplogstarttests.cpp b/src/mongo/dbtests/oplogstarttests.cpp
index 66e0a122875..5742271a6a7 100644
--- a/src/mongo/dbtests/oplogstarttests.cpp
+++ b/src/mongo/dbtests/oplogstarttests.cpp
@@ -30,7 +30,6 @@
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/exec/oplogstart.h"
#include "mongo/db/exec/working_set.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/repl/repl_settings.h"
#include "mongo/db/service_context.h"
@@ -74,8 +73,7 @@ protected:
void setupFromQuery(const BSONObj& query) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
_cq = std::move(statusWithCQ.getValue());
_oplogws.reset(new WorkingSet());
diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp
index a1750c90154..80399f73b06 100644
--- a/src/mongo/dbtests/plan_ranking.cpp
+++ b/src/mongo/dbtests/plan_ranking.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/exec/multi_plan.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/query_knobs.h"
@@ -201,8 +200,7 @@ public:
{
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 100 << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
cq = std::move(statusWithCQ.getValue());
ASSERT(cq.get());
@@ -221,8 +219,7 @@ public:
{
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 100 << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
cq = std::move(statusWithCQ.getValue());
}
@@ -257,8 +254,7 @@ public:
// Run the query {a:1, b:{$gt:1}.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 1 << "b" << BSON("$gt" << 1)));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -299,8 +295,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 27));
qr->setProj(BSON("_id" << 0 << "a" << 1 << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -334,8 +329,7 @@ public:
// There is no data that matches this query but we don't know that until EOF.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 1 << "b" << 1 << "c" << 99));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -374,8 +368,7 @@ public:
qr->setFilter(BSON("a" << 2));
qr->setProj(BSON("_id" << 0 << "a" << 1 << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -408,8 +401,7 @@ public:
// Run the query {a:N+1, b:1}. (No such document.)
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << N + 1 << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -445,8 +437,7 @@ public:
// Run the query {a:N+1, b:1}. (No such document.)
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << BSON("$gte" << N + 1) << "b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -476,8 +467,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("_id" << BSON("$gte" << 20 << "$lte" << 200)));
qr->setSort(BSON("c" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -506,8 +496,7 @@ public:
// Look for A Space Odyssey.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("foo" << 2001));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -541,8 +530,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 1));
qr->setSort(BSON("d" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -579,8 +567,7 @@ public:
// than an index scan on 'a'.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 1, b: 1, c: {$gte: 5000}}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -612,8 +599,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: 9, b: {$ne: 10}, c: 9}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp
index 839f69cff5d..4b1a1eef0e4 100644
--- a/src/mongo/dbtests/query_plan_executor.cpp
+++ b/src/mongo/dbtests/query_plan_executor.cpp
@@ -44,7 +44,6 @@
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/pipeline/document_source_cursor.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
@@ -105,8 +104,7 @@ public:
// Canonicalize the query.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(filterObj);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
verify(NULL != cq.get());
@@ -157,8 +155,7 @@ public:
unique_ptr<PlanStage> root(new FetchStage(&_opCtx, ws.get(), ix, NULL, coll));
auto qr = stdx::make_unique<QueryRequest>(nss);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
verify(NULL != cq.get());
diff --git a/src/mongo/dbtests/query_stage_cached_plan.cpp b/src/mongo/dbtests/query_stage_cached_plan.cpp
index 196e21e2a7c..d020971fecd 100644
--- a/src/mongo/dbtests/query_stage_cached_plan.cpp
+++ b/src/mongo/dbtests/query_stage_cached_plan.cpp
@@ -38,7 +38,6 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/query/get_executor.h"
@@ -123,8 +122,7 @@ public:
// Query can be answered by either index on "a" or index on "b".
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: {$gte: 8}, b: 1}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -191,8 +189,7 @@ public:
// Query can be answered by either index on "a" or index on "b".
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{a: {$gte: 8}, b: 1}"));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
diff --git a/src/mongo/dbtests/query_stage_collscan.cpp b/src/mongo/dbtests/query_stage_collscan.cpp
index d8e0088807c..d17dbdbbcfa 100644
--- a/src/mongo/dbtests/query_stage_collscan.cpp
+++ b/src/mongo/dbtests/query_stage_collscan.cpp
@@ -42,7 +42,6 @@
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/db/storage/record_store.h"
@@ -94,8 +93,8 @@ public:
// Make the filter.
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterObj, collator);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp
index a66c4d5ab38..130cd6e3e4b 100644
--- a/src/mongo/dbtests/query_stage_count.cpp
+++ b/src/mongo/dbtests/query_stage_count.cpp
@@ -42,7 +42,6 @@
#include "mongo/db/exec/working_set.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/dbtests/dbtests.h"
namespace QueryStageCount {
@@ -150,8 +149,8 @@ public:
unique_ptr<WorkingSet> ws(new WorkingSet);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- request.getQuery(), ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(request.getQuery(), collator);
ASSERT(statusWithMatcher.isOK());
unique_ptr<MatchExpression> expression = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/dbtests/query_stage_delete.cpp b/src/mongo/dbtests/query_stage_delete.cpp
index b3892c41ffa..97e7166a478 100644
--- a/src/mongo/dbtests/query_stage_delete.cpp
+++ b/src/mongo/dbtests/query_stage_delete.cpp
@@ -41,7 +41,6 @@
#include "mongo/db/exec/collection_scan.h"
#include "mongo/db/exec/delete.h"
#include "mongo/db/exec/queued_data_stage.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/service_context.h"
#include "mongo/dbtests/dbtests.h"
@@ -106,8 +105,7 @@ public:
unique_ptr<CanonicalQuery> canonicalize(const BSONObj& query) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
diff --git a/src/mongo/dbtests/query_stage_fetch.cpp b/src/mongo/dbtests/query_stage_fetch.cpp
index ee8c5ec2b19..e866d2df9c9 100644
--- a/src/mongo/dbtests/query_stage_fetch.cpp
+++ b/src/mongo/dbtests/query_stage_fetch.cpp
@@ -43,7 +43,6 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/stdx/memory.h"
@@ -195,8 +194,8 @@ public:
// Make the filter.
BSONObj filterObj = BSON("foo" << 6);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterObj, collator);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index c0043192e51..0f02e120110 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -42,7 +42,6 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/db/query/plan_executor.h"
@@ -165,8 +164,8 @@ public:
// Make the filter.
BSONObj filterObj = BSON("foo" << 7);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterObj, collator);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filter = std::move(statusWithMatcher.getValue());
// Make the stage.
@@ -176,8 +175,7 @@ public:
// Hand the plans off to the MPS.
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("foo" << 7));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
verify(NULL != cq.get());
@@ -235,8 +233,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("a" << 1 << "b" << 1));
qr->setSort(BSON("b" << 1));
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
verify(statusWithCQ.isOK());
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
ASSERT(NULL != cq.get());
@@ -340,8 +337,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("x" << 1));
- auto cq = uassertStatusOK(CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = uassertStatusOK(CanonicalQuery::canonicalize(opCtx(), std::move(qr)));
unique_ptr<MultiPlanStage> mps =
make_unique<MultiPlanStage>(&_opCtx, ctx.getCollection(), cq.get());
@@ -417,8 +413,7 @@ public:
// Create the executor (Matching all documents).
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(BSON("foo" << BSON("$gte" << 0)));
- auto cq = uassertStatusOK(CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = uassertStatusOK(CanonicalQuery::canonicalize(opCtx(), std::move(qr)));
auto exec =
uassertStatusOK(getExecutor(&_opCtx, coll, std::move(cq), PlanExecutor::NO_YIELD));
diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp
index 4450434b977..bca6559c25e 100644
--- a/src/mongo/dbtests/query_stage_subplan.cpp
+++ b/src/mongo/dbtests/query_stage_subplan.cpp
@@ -38,8 +38,8 @@
#include "mongo/db/exec/subplan.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/dbtests/dbtests.h"
@@ -79,8 +79,13 @@ protected:
bool isExplain = false;
auto qr = unittest::assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto cq = unittest::assertGet(
- CanonicalQuery::canonicalize(opCtx(), std::move(qr), ExtensionsCallbackNoop()));
+ CanonicalQuery::canonicalize(opCtx(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures));
return cq;
}
@@ -115,8 +120,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -161,8 +165,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -219,8 +222,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -278,8 +280,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(opCtx(), std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
@@ -461,8 +462,7 @@ public:
{
BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression expr = MatchExpressionParser::parse(
- queryObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, collator);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
@@ -479,8 +479,7 @@ public:
{
BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1, f:1}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression expr = MatchExpressionParser::parse(
- queryObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, collator);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
@@ -497,8 +496,7 @@ public:
{
BSONObj queryObj = fromjson("{$or:[{a:1,b:1}, {c:1,d:1}], e:1,f:1}");
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression expr = MatchExpressionParser::parse(
- queryObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, collator);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
@@ -534,8 +532,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto cq = unittest::assertGet(CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = unittest::assertGet(CanonicalQuery::canonicalize(opCtx(), std::move(qr)));
Collection* collection = ctx.getCollection();
@@ -596,8 +593,7 @@ public:
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(fromjson("{$or: [{a: 1}, {a: {$ne:1}}]}"));
qr->setSort(BSON("d" << 1));
- auto cq = unittest::assertGet(CanonicalQuery::canonicalize(
- opCtx(), std::move(qr), ExtensionsCallbackDisallowExtensions()));
+ auto cq = unittest::assertGet(CanonicalQuery::canonicalize(opCtx(), std::move(qr)));
Collection* collection = ctx.getCollection();
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index 474dad6fb4d..6b7893798e5 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -39,7 +39,6 @@
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/dbtests/dbtests.h"
@@ -83,8 +82,8 @@ public:
AutoGetCollectionForReadCommand ctx(&_opCtx, NamespaceString(ns()));
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- filterObj, ExtensionsCallbackDisallowExtensions(), collator);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(filterObj, collator);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/dbtests/query_stage_update.cpp b/src/mongo/dbtests/query_stage_update.cpp
index 4a066a33813..7ccd6058545 100644
--- a/src/mongo/dbtests/query_stage_update.cpp
+++ b/src/mongo/dbtests/query_stage_update.cpp
@@ -45,7 +45,6 @@
#include "mongo/db/exec/working_set.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
-#include "mongo/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/ops/update_lifecycle_impl.h"
#include "mongo/db/ops/update_request.h"
@@ -91,8 +90,7 @@ public:
unique_ptr<CanonicalQuery> canonicalize(const BSONObj& query) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(query);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- &_opCtx, std::move(qr), ExtensionsCallbackDisallowExtensions());
+ auto statusWithCQ = CanonicalQuery::canonicalize(&_opCtx, std::move(qr));
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp
index 1b09f52f577..3ec757bb218 100644
--- a/src/mongo/s/chunk_manager.cpp
+++ b/src/mongo/s/chunk_manager.cpp
@@ -113,8 +113,14 @@ void ChunkManager::getShardIdsForQuery(OperationContext* opCtx,
qr->setCollation(_defaultCollator->getSpec().toBSON());
}
- std::unique_ptr<CanonicalQuery> cq = uassertStatusOK(
- CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackNoop()));
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto cq = uassertStatusOK(
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr));
// Query validation
if (QueryPlannerCommon::hasNode(cq->root(), MatchExpression::GEO_NEAR)) {
diff --git a/src/mongo/s/chunk_manager_index_bounds_test.cpp b/src/mongo/s/chunk_manager_index_bounds_test.cpp
index 5a6aa4ec7bf..9ffc73d0a1c 100644
--- a/src/mongo/s/chunk_manager_index_bounds_test.cpp
+++ b/src/mongo/s/chunk_manager_index_bounds_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/s/chunk_manager.h"
#include "mongo/s/shard_key_pattern.h"
@@ -56,8 +57,14 @@ protected:
const NamespaceString nss("test.foo");
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(queryObj);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- operationContext(), std::move(qr), ExtensionsCallbackNoop());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto statusWithCQ =
+ CanonicalQuery::canonicalize(operationContext(),
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures);
+
ASSERT_OK(statusWithCQ.getStatus());
return std::move(statusWithCQ.getValue());
}
diff --git a/src/mongo/s/commands/chunk_manager_targeter.cpp b/src/mongo/s/commands/chunk_manager_targeter.cpp
index f383c7de312..7b58421ebd3 100644
--- a/src/mongo/s/commands/chunk_manager_targeter.cpp
+++ b/src/mongo/s/commands/chunk_manager_targeter.cpp
@@ -413,7 +413,13 @@ Status ChunkManagerTargeter::targetUpdate(
if (!collation.isEmpty()) {
qr->setCollation(collation);
}
- auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackNoop());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto cq = CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!cq.isOK()) {
return Status(cq.getStatus().code(),
str::stream() << "Could not parse update query " << updateDoc.getQ()
@@ -486,7 +492,13 @@ Status ChunkManagerTargeter::targetDelete(
if (!collation.isEmpty()) {
qr->setCollation(collation);
}
- auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackNoop());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto cq = CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!cq.isOK()) {
return Status(cq.getStatus().code(),
str::stream() << "Could not parse delete query " << deleteDoc.getQ()
diff --git a/src/mongo/s/commands/cluster_find_cmd.cpp b/src/mongo/s/commands/cluster_find_cmd.cpp
index 381638eca5b..8dbef24be73 100644
--- a/src/mongo/s/commands/cluster_find_cmd.cpp
+++ b/src/mongo/s/commands/cluster_find_cmd.cpp
@@ -164,8 +164,13 @@ public:
return appendCommandStatus(result, qr.getStatus());
}
- auto cq =
- CanonicalQuery::canonicalize(opCtx, std::move(qr.getValue()), ExtensionsCallbackNoop());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto cq = CanonicalQuery::canonicalize(opCtx,
+ std::move(qr.getValue()),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!cq.isOK()) {
return appendCommandStatus(result, cq.getStatus());
}
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 1e14c1cb99a..8c76c48b0d5 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -346,8 +346,14 @@ DbResponse Strategy::queryOp(OperationContext* opCtx, const NamespaceString& nss
ReadPreferenceSetting::get(opCtx) =
uassertStatusOK(ReadPreferenceSetting::fromContainingBSON(q.query, defaultReadPref));
- auto canonicalQuery =
- uassertStatusOK(CanonicalQuery::canonicalize(opCtx, q, ExtensionsCallbackNoop()));
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
+ auto canonicalQuery = uassertStatusOK(
+ CanonicalQuery::canonicalize(opCtx,
+ q,
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr));
// If the $explain flag was set, we must run the operation on the shards as an explain command
// rather than a find command.
diff --git a/src/mongo/s/shard_key_pattern.cpp b/src/mongo/s/shard_key_pattern.cpp
index cb9b0883ff9..baefac56f4f 100644
--- a/src/mongo/s/shard_key_pattern.cpp
+++ b/src/mongo/s/shard_key_pattern.cpp
@@ -283,8 +283,14 @@ StatusWith<BSONObj> ShardKeyPattern::extractShardKeyFromQuery(OperationContext*
auto qr = stdx::make_unique<QueryRequest>(NamespaceString(""));
qr->setFilter(basicQuery);
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
- CanonicalQuery::canonicalize(opCtx, std::move(qr), ExtensionsCallbackNoop());
+ CanonicalQuery::canonicalize(opCtx,
+ std::move(qr),
+ expCtx,
+ ExtensionsCallbackNoop(),
+ MatchExpressionParser::kAllowAllSpecialFeatures &
+ ~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithCQ.isOK()) {
return StatusWith<BSONObj>(statusWithCQ.getStatus());
}