summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp23
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.h6
-rw-r--r--src/mongo/db/auth/role_graph_update.cpp3
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp2
-rw-r--r--src/mongo/db/catalog/collection.h7
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp13
-rw-r--r--src/mongo/db/catalog/collection_impl.h1
-rw-r--r--src/mongo/db/catalog/collection_mock.h4
-rw-r--r--src/mongo/db/catalog/database_impl.cpp5
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp4
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp4
-rw-r--r--src/mongo/db/commands/list_collections.cpp3
-rw-r--r--src/mongo/db/commands/list_databases.cpp4
-rw-r--r--src/mongo/db/exec/SConscript1
-rw-r--r--src/mongo/db/exec/projection.cpp3
-rw-r--r--src/mongo/db/exec/projection_exec.cpp7
-rw-r--r--src/mongo/db/exec/projection_exec.h3
-rw-r--r--src/mongo/db/exec/projection_exec_test.cpp17
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp4
-rw-r--r--src/mongo/db/matcher/SConscript4
-rw-r--r--src/mongo/db/matcher/copyable_match_expression.h32
-rw-r--r--src/mongo/db/matcher/expression_algo_test.cpp142
-rw-r--r--src/mongo/db/matcher/expression_expr_test.cpp25
-rw-r--r--src/mongo/db/matcher/expression_parser.cpp117
-rw-r--r--src/mongo/db/matcher/expression_parser.h31
-rw-r--r--src/mongo/db/matcher/expression_parser_array_test.cpp175
-rw-r--r--src/mongo/db/matcher/expression_parser_geo_test.cpp137
-rw-r--r--src/mongo/db/matcher/expression_parser_leaf_test.cpp747
-rw-r--r--src/mongo/db/matcher/expression_parser_test.cpp136
-rw-r--r--src/mongo/db/matcher/expression_parser_tree.cpp8
-rw-r--r--src/mongo/db/matcher/expression_parser_tree_test.cpp25
-rw-r--r--src/mongo/db/matcher/expression_serialization_test.cpp187
-rw-r--r--src/mongo/db/matcher/expression_with_placeholder.cpp4
-rw-r--r--src/mongo/db/matcher/expression_with_placeholder.h2
-rw-r--r--src/mongo/db/matcher/expression_with_placeholder_test.cpp151
-rw-r--r--src/mongo/db/matcher/matcher.cpp5
-rw-r--r--src/mongo/db/matcher/matcher.h3
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index_test.cpp27
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties_test.cpp25
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp9
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp11
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_match_array_index_test.cpp29
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp42
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp11
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp13
-rw-r--r--src/mongo/db/matcher/schema/expression_parser_schema_test.cpp299
-rw-r--r--src/mongo/db/ops/SConscript117
-rw-r--r--src/mongo/db/ops/modifier_add_to_set.cpp2
-rw-r--r--src/mongo/db/ops/modifier_add_to_set_test.cpp9
-rw-r--r--src/mongo/db/ops/modifier_bit_test.cpp23
-rw-r--r--src/mongo/db/ops/modifier_compare.cpp2
-rw-r--r--src/mongo/db/ops/modifier_compare_test.cpp16
-rw-r--r--src/mongo/db/ops/modifier_current_date_test.cpp30
-rw-r--r--src/mongo/db/ops/modifier_inc_test.cpp11
-rw-r--r--src/mongo/db/ops/modifier_interface.h16
-rw-r--r--src/mongo/db/ops/modifier_pop_test.cpp13
-rw-r--r--src/mongo/db/ops/modifier_pull.cpp4
-rw-r--r--src/mongo/db/ops/modifier_pull_all.cpp2
-rw-r--r--src/mongo/db/ops/modifier_pull_all_test.cpp18
-rw-r--r--src/mongo/db/ops/modifier_pull_test.cpp31
-rw-r--r--src/mongo/db/ops/modifier_push.cpp4
-rw-r--r--src/mongo/db/ops/modifier_push_test.cpp118
-rw-r--r--src/mongo/db/ops/modifier_rename_test.cpp117
-rw-r--r--src/mongo/db/ops/modifier_set.cpp8
-rw-r--r--src/mongo/db/ops/modifier_set.h3
-rw-r--r--src/mongo/db/ops/modifier_set_test.cpp12
-rw-r--r--src/mongo/db/ops/modifier_unset_test.cpp4
-rw-r--r--src/mongo/db/ops/parsed_update.cpp17
-rw-r--r--src/mongo/db/ops/update.cpp8
-rw-r--r--src/mongo/db/ops/update.h4
-rw-r--r--src/mongo/db/pipeline/SConscript25
-rw-r--r--src/mongo/db/pipeline/accumulator_test.cpp12
-rw-r--r--src/mongo/db/pipeline/aggregation_context_fixture.h14
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_match.cpp9
-rw-r--r--src/mongo/db/pipeline/document_source_match_test.cpp8
-rw-r--r--src/mongo/db/pipeline/expression_context.cpp45
-rw-r--r--src/mongo/db/pipeline/expression_context.h30
-rw-r--r--src/mongo/db/pipeline/expression_context_for_test.h30
-rw-r--r--src/mongo/db/query/SConscript8
-rw-r--r--src/mongo/db/query/canonical_query.cpp19
-rw-r--r--src/mongo/db/query/canonical_query.h3
-rw-r--r--src/mongo/db/query/canonical_query_test.cpp6
-rw-r--r--src/mongo/db/query/get_executor.cpp2
-rw-r--r--src/mongo/db/query/index_bounds_builder_test.cpp5
-rw-r--r--src/mongo/db/query/parsed_projection.cpp7
-rw-r--r--src/mongo/db/query/parsed_projection.h3
-rw-r--r--src/mongo/db/query/parsed_projection_test.cpp25
-rw-r--r--src/mongo/db/query/plan_cache_indexability_test.cpp5
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp18
-rw-r--r--src/mongo/db/query/planner_ixselect_test.cpp5
-rw-r--r--src/mongo/db/query/query_planner_test_fixture.cpp12
-rw-r--r--src/mongo/db/query/query_planner_test_lib.cpp5
-rw-r--r--src/mongo/db/query/query_solution_test.cpp11
-rw-r--r--src/mongo/db/repl/apply_ops.cpp3
-rw-r--r--src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp2
-rw-r--r--src/mongo/db/update/SConscript2
-rw-r--r--src/mongo/db/update/addtoset_node.cpp5
-rw-r--r--src/mongo/db/update/addtoset_node.h2
-rw-r--r--src/mongo/db/update/addtoset_node_test.cpp116
-rw-r--r--src/mongo/db/update/arithmetic_node.cpp3
-rw-r--r--src/mongo/db/update/arithmetic_node.h2
-rw-r--r--src/mongo/db/update/arithmetic_node_test.cpp257
-rw-r--r--src/mongo/db/update/bit_node.cpp2
-rw-r--r--src/mongo/db/update/bit_node.h2
-rw-r--r--src/mongo/db/update/bit_node_test.cpp97
-rw-r--r--src/mongo/db/update/compare_node.cpp5
-rw-r--r--src/mongo/db/update/compare_node.h2
-rw-r--r--src/mongo/db/update/compare_node_test.cpp94
-rw-r--r--src/mongo/db/update/conflict_placeholder_node.h2
-rw-r--r--src/mongo/db/update/current_date_node.cpp3
-rw-r--r--src/mongo/db/update/current_date_node.h2
-rw-r--r--src/mongo/db/update/current_date_node_test.cpp73
-rw-r--r--src/mongo/db/update/path_support_test.cpp5
-rw-r--r--src/mongo/db/update/pop_node.cpp2
-rw-r--r--src/mongo/db/update/pop_node.h2
-rw-r--r--src/mongo/db/update/pop_node_test.cpp105
-rw-r--r--src/mongo/db/update/pull_node.cpp17
-rw-r--r--src/mongo/db/update/pull_node.h2
-rw-r--r--src/mongo/db/update/pull_node_test.cpp161
-rw-r--r--src/mongo/db/update/pullall_node.cpp5
-rw-r--r--src/mongo/db/update/pullall_node.h2
-rw-r--r--src/mongo/db/update/pullall_node_test.cpp65
-rw-r--r--src/mongo/db/update/push_node.cpp6
-rw-r--r--src/mongo/db/update/push_node.h2
-rw-r--r--src/mongo/db/update/push_node_test.cpp229
-rw-r--r--src/mongo/db/update/rename_node.cpp5
-rw-r--r--src/mongo/db/update/rename_node.h2
-rw-r--r--src/mongo/db/update/rename_node_test.cpp137
-rw-r--r--src/mongo/db/update/set_node.cpp2
-rw-r--r--src/mongo/db/update/set_node.h2
-rw-r--r--src/mongo/db/update/set_node_test.cpp309
-rw-r--r--src/mongo/db/update/unset_node.cpp2
-rw-r--r--src/mongo/db/update/unset_node.h2
-rw-r--r--src/mongo/db/update/unset_node_test.cpp97
-rw-r--r--src/mongo/db/update/update_array_node_test.cpp179
-rw-r--r--src/mongo/db/update/update_driver.cpp8
-rw-r--r--src/mongo/db/update/update_driver.h3
-rw-r--r--src/mongo/db/update/update_driver_test.cpp43
-rw-r--r--src/mongo/db/update/update_leaf_node.h10
-rw-r--r--src/mongo/db/update/update_object_node.cpp6
-rw-r--r--src/mongo/db/update/update_object_node.h2
-rw-r--r--src/mongo/db/update/update_object_node_test.cpp629
-rw-r--r--src/mongo/db/views/view_catalog.cpp2
-rw-r--r--src/mongo/dbtests/SConscript1
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp12
-rw-r--r--src/mongo/dbtests/matchertests.cpp60
-rw-r--r--src/mongo/dbtests/query_stage_collscan.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_count.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_fetch.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp12
-rw-r--r--src/mongo/dbtests/query_stage_subplan.cpp12
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp4
-rw-r--r--src/mongo/dbtests/query_stage_update.cpp15
-rw-r--r--src/mongo/s/SConscript1
155 files changed, 3141 insertions, 3114 deletions
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 ca77d4184a7..fbf8a3b2251 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -112,7 +112,7 @@ Status AuthzManagerExternalStateMock::findOne(OperationContext* opCtx,
const BSONObj& query,
BSONObj* result) {
BSONObjCollection::iterator iter;
- Status status = _findOneIter(collectionName, query, &iter);
+ Status status = _findOneIter(opCtx, collectionName, query, &iter);
if (!status.isOK())
return status;
*result = iter->copy();
@@ -126,7 +126,7 @@ Status AuthzManagerExternalStateMock::query(
const BSONObj&,
const stdx::function<void(const BSONObj&)>& resultProcessor) {
std::vector<BSONObjCollection::iterator> iterVector;
- Status status = _queryVector(collectionName, query, &iterVector);
+ Status status = _queryVector(opCtx, collectionName, query, &iterVector);
if (!status.isOK()) {
return status;
}
@@ -177,7 +177,9 @@ Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx,
bool upsert,
const BSONObj& writeConcern) {
namespace mmb = mutablebson;
- UpdateDriver::Options updateOptions;
+ const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
+ UpdateDriver::Options updateOptions(std::move(expCtx));
UpdateDriver driver(updateOptions);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
Status status = driver.parse(updatePattern, arrayFilters);
@@ -185,7 +187,7 @@ Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx,
return status;
BSONObjCollection::iterator iter;
- status = _findOneIter(collectionName, query, &iter);
+ status = _findOneIter(opCtx, collectionName, query, &iter);
mmb::Document document;
if (status.isOK()) {
document.reset(*iter, mmb::Document::kInPlaceDisabled);
@@ -257,7 +259,7 @@ Status AuthzManagerExternalStateMock::remove(OperationContext* opCtx,
int* numRemoved) {
int n = 0;
BSONObjCollection::iterator iter;
- while (_findOneIter(collectionName, query, &iter).isOK()) {
+ while (_findOneIter(opCtx, collectionName, query, &iter).isOK()) {
BSONObj idQuery = (*iter)["_id"].wrap();
_documents[collectionName].erase(iter);
++n;
@@ -275,11 +277,12 @@ std::vector<BSONObj> AuthzManagerExternalStateMock::getCollectionContents(
return mapFindWithDefault(_documents, collectionName, std::vector<BSONObj>());
}
-Status AuthzManagerExternalStateMock::_findOneIter(const NamespaceString& collectionName,
+Status AuthzManagerExternalStateMock::_findOneIter(OperationContext* opCtx,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObjCollection::iterator* result) {
std::vector<BSONObjCollection::iterator> iterVector;
- Status status = _queryVector(collectionName, query, &iterVector);
+ Status status = _queryVector(opCtx, collectionName, query, &iterVector);
if (!status.isOK()) {
return status;
}
@@ -291,11 +294,13 @@ Status AuthzManagerExternalStateMock::_findOneIter(const NamespaceString& collec
}
Status AuthzManagerExternalStateMock::_queryVector(
+ OperationContext* opCtx,
const NamespaceString& collectionName,
const BSONObj& query,
std::vector<BSONObjCollection::iterator>* result) {
- CollatorInterface* collator = nullptr;
- StatusWithMatchExpression parseResult = MatchExpressionParser::parse(query, collator);
+ const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(query, std::move(expCtx));
if (!parseResult.isOK()) {
return parseResult.getStatus();
}
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.h b/src/mongo/db/auth/authz_manager_external_state_mock.h
index 4d90099f120..0cfe9b9d775 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.h
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.h
@@ -112,11 +112,13 @@ private:
typedef std::vector<BSONObj> BSONObjCollection;
typedef std::map<NamespaceString, BSONObjCollection> NamespaceDocumentMap;
- Status _findOneIter(const NamespaceString& collectionName,
+ Status _findOneIter(OperationContext* opCtx,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObjCollection::iterator* result);
- Status _queryVector(const NamespaceString& collectionName,
+ Status _queryVector(OperationContext* opCtx,
+ const NamespaceString& collectionName,
const BSONObj& query,
std::vector<BSONObjCollection::iterator>* result);
diff --git a/src/mongo/db/auth/role_graph_update.cpp b/src/mongo/db/auth/role_graph_update.cpp
index 9b5629cd3ab..96988cd5d80 100644
--- a/src/mongo/db/auth/role_graph_update.cpp
+++ b/src/mongo/db/auth/role_graph_update.cpp
@@ -202,7 +202,8 @@ Status handleOplogUpdate(OperationContext* opCtx,
if (!status.isOK())
return status;
- UpdateDriver::Options updateOptions;
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, nullptr));
+ UpdateDriver::Options updateOptions(std::move(expCtx));
updateOptions.modOptions.fromOplogApplication = true;
UpdateDriver driver(updateOptions);
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 59e8623ac7a..1a24d9a8caa 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -180,7 +180,7 @@ StatusWith<CollModRequest> parseCollModRequest(OperationContext* opCtx,
// instances, as indicated by !validateFeaturesAsMaster.
allowedFeatures |= MatchExpressionParser::kJSONSchema;
}
- auto statusW = coll->parseValidator(e.Obj(), allowedFeatures);
+ auto statusW = coll->parseValidator(opCtx, e.Obj(), allowedFeatures);
if (!statusW.isOK()) {
if (statusW.getStatus().code() == ErrorCodes::JSONSchemaNotAllowed) {
// The default error message for disallowed $jsonSchema is not descriptive
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index fd0f9b3b1b4..5d30401e2b6 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -302,6 +302,7 @@ public:
virtual void cappedTruncateAfter(OperationContext* opCtx, RecordId end, bool inclusive) = 0;
virtual StatusWithMatchExpression parseValidator(
+ OperationContext* opCtx,
const BSONObj& validator,
MatchExpressionParser::AllowedFeatureSet allowedFeatures) const = 0;
@@ -627,8 +628,10 @@ public:
* Returns a non-ok Status if validator is not legal for this collection.
*/
inline StatusWithMatchExpression parseValidator(
- const BSONObj& validator, MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
- return this->_impl().parseValidator(validator, allowedFeatures);
+ OperationContext* opCtx,
+ const BSONObj& validator,
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
+ return this->_impl().parseValidator(opCtx, validator, allowedFeatures);
}
static StatusWith<ValidationLevel> parseValidationLevel(StringData);
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 26af94b10ff..f41d9d2a467 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -160,7 +160,8 @@ CollectionImpl::CollectionImpl(Collection* _this_init,
_collator(parseCollation(opCtx, _ns, _details->getCollectionOptions(opCtx).collation)),
_validatorDoc(_details->getCollectionOptions(opCtx).validator.getOwned()),
_validator(
- uassertStatusOK(parseValidator(_validatorDoc,
+ uassertStatusOK(parseValidator(opCtx,
+ _validatorDoc,
MatchExpressionParser::kAllowAllSpecialFeatures &
~MatchExpressionParser::AllowedFeatures::kExpr))),
_validationAction(uassertStatusOK(
@@ -268,7 +269,9 @@ Status CollectionImpl::checkValidation(OperationContext* opCtx, const BSONObj& d
}
StatusWithMatchExpression CollectionImpl::parseValidator(
- const BSONObj& validator, MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
+ OperationContext* opCtx,
+ const BSONObj& validator,
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
if (validator.isEmpty())
return {nullptr};
@@ -285,8 +288,9 @@ StatusWithMatchExpression CollectionImpl::parseValidator(
<< " database"};
}
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, _collator.get()));
auto statusWithMatcher = MatchExpressionParser::parse(
- validator, _collator.get(), nullptr, ExtensionsCallbackNoop(), allowedFeatures);
+ validator, std::move(expCtx), ExtensionsCallbackNoop(), allowedFeatures);
if (!statusWithMatcher.isOK())
return statusWithMatcher.getStatus();
@@ -894,7 +898,8 @@ Status CollectionImpl::setValidator(OperationContext* opCtx, BSONObj validatorDo
// Note that, by the time we reach this, we should have already done a pre-parse that checks for
// banned features, so we don't need to include that check again.
- auto statusWithMatcher = parseValidator(validatorDoc,
+ auto statusWithMatcher = parseValidator(opCtx,
+ validatorDoc,
MatchExpressionParser::kAllowAllSpecialFeatures &
~MatchExpressionParser::AllowedFeatures::kExpr);
if (!statusWithMatcher.isOK())
diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h
index f8db017330e..cba3445042e 100644
--- a/src/mongo/db/catalog/collection_impl.h
+++ b/src/mongo/db/catalog/collection_impl.h
@@ -284,6 +284,7 @@ public:
* Returns a non-ok Status if validator is not legal for this collection.
*/
StatusWithMatchExpression parseValidator(
+ OperationContext* opCtx,
const BSONObj& validator,
MatchExpressionParser::AllowedFeatureSet allowedFeatures) const final;
diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h
index e9ecffc144b..405a3fde968 100644
--- a/src/mongo/db/catalog/collection_mock.h
+++ b/src/mongo/db/catalog/collection_mock.h
@@ -221,7 +221,9 @@ public:
}
StatusWithMatchExpression parseValidator(
- const BSONObj& validator, MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
+ OperationContext* opCtx,
+ const BSONObj& validator,
+ MatchExpressionParser::AllowedFeatureSet allowedFeatures) const {
std::abort();
}
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 5f6f7d61748..ad186e8f06b 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -1013,9 +1013,10 @@ auto mongo::userCreateNSImpl(OperationContext* opCtx,
// the secondary or on a backup instance, as indicated by !validateFeaturesAsMaster.
allowedFeatures |= MatchExpressionParser::kJSONSchema;
}
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, collator.get()));
auto statusWithMatcher = MatchExpressionParser::parse(collectionOptions.validator,
- collator.get(),
- nullptr,
+ std::move(expCtx),
ExtensionsCallbackNoop(),
allowedFeatures);
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index 7f46d56dac8..afa073f7ce0 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -127,8 +127,10 @@ IndexCatalogEntryImpl::IndexCatalogEntryImpl(IndexCatalogEntry* const this_,
if (BSONElement filterElement = _descriptor->getInfoElement("partialFilterExpression")) {
invariant(filterElement.isABSONObj());
BSONObj filter = filterElement.Obj();
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, _collator.get()));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filter, _collator.get());
+ MatchExpressionParser::parse(filter, std::move(expCtx));
// 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 b128061a1c1..726dc2f5e28 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -666,8 +666,10 @@ Status IndexCatalogImpl::_isSpecOk(OperationContext* opCtx, const BSONObj& spec)
}
// The collator must outlive the constructed MatchExpression.
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, collator.get()));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filterElement.Obj(), collator.get());
+ MatchExpressionParser::parse(filterElement.Obj(), std::move(expCtx));
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index c952573ac14..20560d3a4c9 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -244,8 +244,9 @@ public:
}
// The collator is null because collection objects are compared using binary comparison.
const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filterElt.Obj(), collator);
+ MatchExpressionParser::parse(filterElt.Obj(), std::move(expCtx));
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 232803320d0..fb719e1bda6 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -99,7 +99,9 @@ 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(), collator);
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
+ auto statusWithMatcher =
+ MatchExpressionParser::parse(filterElt.Obj(), std::move(expCtx));
if (!statusWithMatcher.isOK()) {
return appendCommandStatus(result, statusWithMatcher.getStatus());
}
diff --git a/src/mongo/db/exec/SConscript b/src/mongo/db/exec/SConscript
index 409ada6c1dd..04dd3a7e647 100644
--- a/src/mongo/db/exec/SConscript
+++ b/src/mongo/db/exec/SConscript
@@ -153,6 +153,7 @@ env.CppUnitTest(
],
LIBDEPS = [
"$BUILD_DIR/mongo/db/query/collation/collator_interface_mock",
+ "$BUILD_DIR/mongo/db/query/query_test_service_context",
"$BUILD_DIR/mongo/db/serveronly",
"exec",
],
diff --git a/src/mongo/db/exec/projection.cpp b/src/mongo/db/exec/projection.cpp
index 65ee238c4a0..370a8e87892 100644
--- a/src/mongo/db/exec/projection.cpp
+++ b/src/mongo/db/exec/projection.cpp
@@ -61,7 +61,8 @@ ProjectionStage::ProjectionStage(OperationContext* opCtx,
_projObj = params.projObj;
if (ProjectionStageParams::NO_FAST_PATH == _projImpl) {
- _exec.reset(new ProjectionExec(params.projObj, params.fullExpression, params.collator));
+ _exec.reset(
+ new ProjectionExec(opCtx, 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_exec.cpp b/src/mongo/db/exec/projection_exec.cpp
index d4842ac1e74..ae17257c9ef 100644
--- a/src/mongo/db/exec/projection_exec.cpp
+++ b/src/mongo/db/exec/projection_exec.cpp
@@ -77,7 +77,8 @@ ProjectionExec::ProjectionExec()
_queryExpression(NULL),
_hasReturnKey(false) {}
-ProjectionExec::ProjectionExec(const BSONObj& spec,
+ProjectionExec::ProjectionExec(OperationContext* opCtx,
+ const BSONObj& spec,
const MatchExpression* queryExpression,
const CollatorInterface* collator)
: _include(true),
@@ -131,8 +132,10 @@ ProjectionExec::ProjectionExec(const BSONObj& spec,
BSONObj elemMatchObj = e.wrap();
verify(elemMatchObj.isOwned());
_elemMatchObjs.push_back(elemMatchObj);
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, _collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(elemMatchObj, _collator);
+ MatchExpressionParser::parse(elemMatchObj, std::move(expCtx));
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 9575d59042f..829cdf0d43a 100644
--- a/src/mongo/db/exec/projection_exec.h
+++ b/src/mongo/db/exec/projection_exec.h
@@ -66,7 +66,8 @@ public:
typedef StringMap<MatchExpression*> Matchers;
typedef StringMap<MetaProjection> MetaMap;
- ProjectionExec(const BSONObj& spec,
+ ProjectionExec(OperationContext* opCtx,
+ const BSONObj& spec,
const MatchExpression* queryExpression,
const CollatorInterface* collator);
diff --git a/src/mongo/db/exec/projection_exec_test.cpp b/src/mongo/db/exec/projection_exec_test.cpp
index 41c40c2b287..b5e10f92bd9 100644
--- a/src/mongo/db/exec/projection_exec_test.cpp
+++ b/src/mongo/db/exec/projection_exec_test.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/exec/working_set_computed_data.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/unittest.h"
#include <memory>
@@ -49,8 +50,8 @@ using std::unique_ptr;
* Utility function to create MatchExpression
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
ASSERT_TRUE(status.isOK());
return std::move(status.getValue());
}
@@ -83,7 +84,9 @@ 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);
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
+ ProjectionExec exec(opCtx.get(), spec, queryExpression.get(), collator);
// Create working set member.
WorkingSetMember wsm;
@@ -166,7 +169,9 @@ BSONObj transformMetaSortKeyCovered(const BSONObj& sortKey,
wsm->addComputed(new SortKeyComputedData(sortKey));
ws.transitionToRecordIdAndIdx(wsid);
- ProjectionExec projExec(fromjson(projSpec), nullptr, nullptr);
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
+ ProjectionExec projExec(opCtx.get(), fromjson(projSpec), nullptr, nullptr);
ASSERT_OK(projExec.transform(wsm));
return wsm->obj.value();
@@ -179,7 +184,9 @@ BSONObj transformCovered(BSONObj projSpec, const IndexKeyDatum& ikd) {
wsm->keyData.push_back(ikd);
ws.transitionToRecordIdAndIdx(wsid);
- ProjectionExec projExec(projSpec, nullptr, nullptr);
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
+ ProjectionExec projExec(opCtx.get(), 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 d8186f637e0..f3d9c92cafd 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -248,10 +248,10 @@ public:
BSONObj argObj = e.Obj();
if (filterTag == e.fieldName()) {
const CollatorInterface* collator = nullptr;
- boost::intrusive_ptr<ExpressionContext> expCtx;
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, collator));
StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
argObj,
- collator,
expCtx,
ExtensionsCallbackReal(opCtx, &collection->ns()),
MatchExpressionParser::kAllowAllSpecialFeatures &
diff --git a/src/mongo/db/matcher/SConscript b/src/mongo/db/matcher/SConscript
index a795325d185..2d4d9341c9e 100644
--- a/src/mongo/db/matcher/SConscript
+++ b/src/mongo/db/matcher/SConscript
@@ -114,6 +114,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'expressions',
],
)
@@ -131,6 +132,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'expressions',
],
)
@@ -143,6 +145,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'expressions',
],
)
@@ -173,6 +176,7 @@ env.CppUnitTest(
'expression_serialization_test.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'expressions',
],
)
diff --git a/src/mongo/db/matcher/copyable_match_expression.h b/src/mongo/db/matcher/copyable_match_expression.h
index a1557b6f382..423a04dc147 100644
--- a/src/mongo/db/matcher/copyable_match_expression.h
+++ b/src/mongo/db/matcher/copyable_match_expression.h
@@ -51,41 +51,23 @@ public:
* encounter an error.
*/
CopyableMatchExpression(BSONObj matchAST,
- const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
std::unique_ptr<const ExtensionsCallback> extensionsCallback =
stdx::make_unique<ExtensionsCallbackNoop>(),
MatchExpressionParser::AllowedFeatureSet allowedFeatures =
MatchExpressionParser::kDefaultSpecialFeatures)
: _matchAST(matchAST), _extensionsCallback(std::move(extensionsCallback)) {
- StatusWithMatchExpression parseResult = MatchExpressionParser::parse(
- _matchAST, collator, expCtx, *_extensionsCallback, allowedFeatures);
+ StatusWithMatchExpression parseResult =
+ MatchExpressionParser::parse(_matchAST, expCtx, *_extensionsCallback, allowedFeatures);
uassertStatusOK(parseResult.getStatus());
_matchExpr = std::move(parseResult.getValue());
}
/**
- * Semantically, this behaves as if the client called setCollator() on the underlying
- * MatchExpression (which is impossible, because it's const).
- *
- * Behind the scenes, it actually makes a new MatchExpression with the new collator. That way,
- * if there other CopyableMatchExpression objects referencing this MatchExpression, they don't
- * see the change in collator.
+ * Sets the collator on the underlying MatchExpression and all clones(!).
*/
- 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());
+ void setCollator(const CollatorInterface* collator) {
+ _matchExpr->setCollator(collator);
}
/**
@@ -107,7 +89,7 @@ public:
private:
BSONObj _matchAST;
std::shared_ptr<const ExtensionsCallback> _extensionsCallback;
- std::shared_ptr<const MatchExpression> _matchExpr;
+ std::shared_ptr<MatchExpression> _matchExpr;
};
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_algo_test.cpp b/src/mongo/db/matcher/expression_algo_test.cpp
index cb803819b69..d1ec11137dd 100644
--- a/src/mongo/db/matcher/expression_algo_test.cpp
+++ b/src/mongo/db/matcher/expression_algo_test.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_algo.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/platform/decimal128.h"
@@ -52,7 +53,9 @@ class ParsedMatchExpression {
public:
ParsedMatchExpression(const std::string& str, const CollatorInterface* collator = nullptr)
: _obj(fromjson(str)) {
- StatusWithMatchExpression result = MatchExpressionParser::parse(_obj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(_obj, std::move(expCtx));
ASSERT_OK(result.getStatus());
_expr = std::move(result.getValue());
}
@@ -70,9 +73,9 @@ TEST(ExpressionAlgoIsSubsetOf, NullAndOmittedField) {
// Verify that ComparisonMatchExpression::init() prohibits creating a match expression with
// an Undefined type.
BSONObj undefined = fromjson("{a: undefined}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_EQUALS(ErrorCodes::BadValue,
- MatchExpressionParser::parse(undefined, collator).getStatus());
+ MatchExpressionParser::parse(undefined, std::move(expCtx)).getStatus());
ParsedMatchExpression empty("{}");
ParsedMatchExpression null("{a: null}");
@@ -708,8 +711,9 @@ TEST(ExpressionAlgoIsSubsetOf, NonMatchingCollationsNoStringComparison) {
TEST(IsIndependent, AndIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -719,8 +723,9 @@ TEST(IsIndependent, AndIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, ElemMatchIsNotIndependent) {
BSONObj matchPredicate = fromjson("{x: {$elemMatch: {y: 1}}}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -731,8 +736,9 @@ TEST(IsIndependent, ElemMatchIsNotIndependent) {
TEST(IsIndependent, NorIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$nor: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -742,8 +748,9 @@ TEST(IsIndependent, NorIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, NotIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -753,8 +760,9 @@ TEST(IsIndependent, NotIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, OrIsIndependentOnlyIfChildrenAre) {
BSONObj matchPredicate = fromjson("{$or: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -764,8 +772,9 @@ TEST(IsIndependent, OrIsIndependentOnlyIfChildrenAre) {
TEST(IsIndependent, AndWithDottedFieldPathsIsNotIndependent) {
BSONObj matchPredicate = fromjson("{$and: [{'a': 1}, {'a.b': 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -775,8 +784,9 @@ TEST(IsIndependent, AndWithDottedFieldPathsIsNotIndependent) {
TEST(IsIndependent, BallIsIndependentOfBalloon) {
BSONObj matchPredicate = fromjson("{'a.ball': 4}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
unique_ptr<MatchExpression> expr = std::move(status.getValue());
@@ -787,8 +797,9 @@ TEST(IsIndependent, BallIsIndependentOfBalloon) {
TEST(SplitMatchExpression, AndWithSplittableChildrenIsSplittable) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -808,8 +819,9 @@ TEST(SplitMatchExpression, AndWithSplittableChildrenIsSplittable) {
TEST(SplitMatchExpression, NorWithIndependentChildrenIsSplittable) {
BSONObj matchPredicate = fromjson("{$nor: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -829,8 +841,9 @@ TEST(SplitMatchExpression, NorWithIndependentChildrenIsSplittable) {
TEST(SplitMatchExpression, NotWithIndependentChildIsSplittable) {
BSONObj matchPredicate = fromjson("{x: {$not: {$gt: 4}}}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -846,8 +859,9 @@ TEST(SplitMatchExpression, NotWithIndependentChildIsSplittable) {
TEST(SplitMatchExpression, OrWithOnlyIndependentChildrenIsNotSplittable) {
BSONObj matchPredicate = fromjson("{$or: [{a: 1}, {b: 1}]}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -866,8 +880,9 @@ TEST(SplitMatchExpression, ComplexMatchExpressionSplitsCorrectly) {
"{$and: [{x: {$not: {$size: 2}}},"
"{$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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -891,8 +906,9 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status =
+ MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(status.getStatus());
std::pair<unique_ptr<MatchExpression>, unique_ptr<MatchExpression>> splitExpr =
@@ -912,8 +928,8 @@ TEST(SplitMatchExpression, ShouldNotExtractPrefixOfDottedPathAsIndependent) {
TEST(SplitMatchExpression, ShouldMoveIndependentLeafPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{a: 1}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "b"}};
@@ -930,8 +946,8 @@ TEST(SplitMatchExpression, ShouldMoveIndependentLeafPredicateAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveIndependentAndPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 2}]}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -948,8 +964,8 @@ TEST(SplitMatchExpression, ShouldMoveIndependentAndPredicateAcrossRename) {
TEST(SplitMatchExpression, ShouldSplitPartiallyDependentAndPredicateAcrossRename) {
BSONObj matchPredicate = fromjson("{$and: [{a: 1}, {b: 2}]}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -969,8 +985,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"b", "d"}, {"c", "e"}};
@@ -991,8 +1007,8 @@ TEST(SplitMatchExpression, ShouldSplitPartiallyDependentComplexPredicateMultiple
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"d.e.f", "x"}, {"e.f.g", "y"}};
@@ -1012,8 +1028,8 @@ TEST(SplitMatchExpression,
TEST(SplitMatchExpression, ShouldNotMoveElemMatchObjectAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {b: 3}}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1030,8 +1046,8 @@ TEST(SplitMatchExpression, ShouldNotMoveElemMatchObjectAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveElemMatchValueAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {$eq: 3}}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1048,8 +1064,8 @@ TEST(SplitMatchExpression, ShouldNotMoveElemMatchValueAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveTypeAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$type: 16}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1066,8 +1082,8 @@ TEST(SplitMatchExpression, ShouldMoveTypeAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveSizeAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$size: 3}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1084,8 +1100,8 @@ TEST(SplitMatchExpression, ShouldNotMoveSizeAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveMinItemsAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMinItems: 3}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1102,8 +1118,8 @@ TEST(SplitMatchExpression, ShouldNotMoveMinItemsAcrossRename) {
TEST(SplitMatchExpression, ShouldNotMoveMaxItemsAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMaxItems: 3}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1120,8 +1136,8 @@ TEST(SplitMatchExpression, ShouldNotMoveMaxItemsAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveMinLengthAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMinLength: 3}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1138,8 +1154,8 @@ TEST(SplitMatchExpression, ShouldMoveMinLengthAcrossRename) {
TEST(SplitMatchExpression, ShouldMoveMaxLengthAcrossRename) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaMaxLength: 3}}");
- const CollatorInterface* collator = nullptr;
- auto matcher = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matcher = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(matcher.getStatus());
StringMap<std::string> renames{{"a", "c"}};
@@ -1156,8 +1172,8 @@ TEST(SplitMatchExpression, ShouldMoveMaxLengthAcrossRename) {
TEST(MapOverMatchExpression, DoesMapOverLogicalNodes) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
- const CollatorInterface* collator = nullptr;
- auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(swMatchExpression.getStatus());
bool hasLogicalNode = false;
@@ -1174,8 +1190,8 @@ TEST(MapOverMatchExpression, DoesMapOverLogicalNodes) {
TEST(MapOverMatchExpression, DoesMapOverLeafNodes) {
BSONObj matchPredicate = fromjson("{a: {$not: {$eq: 1}}}");
- const CollatorInterface* collator = nullptr;
- auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(swMatchExpression.getStatus());
bool hasLeafNode = false;
@@ -1192,8 +1208,8 @@ TEST(MapOverMatchExpression, DoesMapOverLeafNodes) {
TEST(MapOverMatchExpression, DoesPassPath) {
BSONObj matchPredicate = fromjson("{a: {$elemMatch: {b: 1}}}");
- const CollatorInterface* collator = nullptr;
- auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(swMatchExpression.getStatus());
std::vector<std::string> paths;
@@ -1210,8 +1226,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto swMatchExpression = MatchExpressionParser::parse(matchPredicate, std::move(expCtx));
ASSERT_OK(swMatchExpression.getStatus());
size_t nodeCount = 0;
diff --git a/src/mongo/db/matcher/expression_expr_test.cpp b/src/mongo/db/matcher/expression_expr_test.cpp
index e0dfae1bb38..1d7e6e1b4be 100644
--- a/src/mongo/db/matcher/expression_expr_test.cpp
+++ b/src/mongo/db/matcher/expression_expr_test.cpp
@@ -31,7 +31,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_expr.h"
#include "mongo/db/matcher/matcher.h"
-#include "mongo/db/pipeline/aggregation_context_fixture.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -39,15 +39,12 @@ namespace mongo {
namespace {
TEST(ExprMatchExpression, ComparisonToConstantMatchesCorrectly) {
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- const CollatorInterface* kSimpleCollator = nullptr;
-
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto match = BSON("a" << 5);
auto notMatch = BSON("a" << 6);
auto expression1 = BSON("$expr" << BSON("$eq" << BSON_ARRAY("$a" << 5)));
Matcher matcher1(expression1,
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -59,7 +56,6 @@ TEST(ExprMatchExpression, ComparisonToConstantMatchesCorrectly) {
auto expression2 = BSON("$expr" << BSON("$eq" << BSON_ARRAY("$a"
<< "$$var")));
Matcher matcher2(expression2,
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -68,17 +64,15 @@ TEST(ExprMatchExpression, ComparisonToConstantMatchesCorrectly) {
}
TEST(ExprMatchExpression, ComparisonBetweenTwoFieldPathsMatchesCorrectly) {
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto expression = BSON("$expr" << BSON("$gt" << BSON_ARRAY("$a"
<< "$b")));
auto match = BSON("a" << 10 << "b" << 2);
auto notMatch = BSON("a" << 2 << "b" << 10);
- const CollatorInterface* kSimpleCollator = nullptr;
Matcher matcher(expression,
- kSimpleCollator,
- expCtx,
+ std::move(expCtx),
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -87,10 +81,11 @@ TEST(ExprMatchExpression, ComparisonBetweenTwoFieldPathsMatchesCorrectly) {
}
TEST(ExprMatchExpression, ComparisonThrowsWithUnboundVariable) {
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto expression = BSON("$expr" << BSON("$eq" << BSON_ARRAY("$a"
<< "$$var")));
- ASSERT_THROWS(ExprMatchExpression pipelineExpr(expression.firstElement(), expCtx), DBException);
+ ASSERT_THROWS(ExprMatchExpression pipelineExpr(expression.firstElement(), std::move(expCtx)),
+ DBException);
}
// TODO SERVER-30991: Uncomment once MatchExpression::optimize() is in place and handles
@@ -103,7 +98,7 @@ TEST(ExprMatchExpression, IdenticalPostOptimizedExpressionsAreEquivalent) {
BSONObj expressionEquiv = BSON("$expr" << BSON("$const" << 4));
BSONObj expressionNotEquiv = BSON("$expr" << BSON("$const" << 10));
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ExprMatchExpression pipelineExpr(expression.firstElement(), expCtx);
pipelineExpr::optimize();
ASSERT_TRUE(pipelineExpr.equivalent(&pipelineExpr));
@@ -119,8 +114,8 @@ TEST(ExprMatchExpression, IdenticalPostOptimizedExpressionsAreEquivalent) {
TEST(ExprMatchExpression, ShallowClonedExpressionIsEquivalentToOriginal) {
BSONObj expression = BSON("$expr" << BSON("$eq" << BSON_ARRAY("$a" << 5)));
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- ExprMatchExpression pipelineExpr(expression.firstElement(), expCtx);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ExprMatchExpression pipelineExpr(expression.firstElement(), std::move(expCtx));
auto shallowClone = pipelineExpr.shallowClone();
ASSERT_TRUE(pipelineExpr.equivalent(shallowClone.get()));
}
diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp
index b1dec5b6a33..de8d2717a96 100644
--- a/src/mongo/db/matcher/expression_parser.cpp
+++ b/src/mongo/db/matcher/expression_parser.cpp
@@ -116,7 +116,6 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison(
const char* name,
ComparisonMatchExpression* cmp,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures) {
std::unique_ptr<ComparisonMatchExpression> temp(cmp);
@@ -134,7 +133,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison(
return s;
}
- temp->setCollator(collator);
+ temp->setCollator(expCtx->getCollator());
return {std::move(temp)};
}
@@ -144,16 +143,14 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
const AndMatchExpression* andSoFar,
const char* name,
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, allowedFeatures);
+ return _parseComparison(name, new EqualityMatchExpression(), e, expCtx, allowedFeatures);
if (mongoutils::str::equals("$not", e.fieldName())) {
- return _parseNot(name, e, collator, expCtx, allowedFeatures, topLevel);
+ return _parseNot(name, e, expCtx, allowedFeatures, topLevel);
}
auto parseExpMatchType = MatchExpressionParser::parsePathAcceptingKeyword(e);
@@ -169,25 +166,21 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
switch (*parseExpMatchType) {
case PathAcceptingKeyword::LESS_THAN:
- return _parseComparison(
- name, new LTMatchExpression(), e, collator, expCtx, allowedFeatures);
+ return _parseComparison(name, new LTMatchExpression(), e, expCtx, allowedFeatures);
case PathAcceptingKeyword::LESS_THAN_OR_EQUAL:
- return _parseComparison(
- name, new LTEMatchExpression(), e, collator, expCtx, allowedFeatures);
+ return _parseComparison(name, new LTEMatchExpression(), e, expCtx, allowedFeatures);
case PathAcceptingKeyword::GREATER_THAN:
- return _parseComparison(
- name, new GTMatchExpression(), e, collator, expCtx, allowedFeatures);
+ return _parseComparison(name, new GTMatchExpression(), e, expCtx, allowedFeatures);
case PathAcceptingKeyword::GREATER_THAN_OR_EQUAL:
- return _parseComparison(
- name, new GTEMatchExpression(), e, collator, expCtx, allowedFeatures);
+ return _parseComparison(name, new GTEMatchExpression(), e, 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, allowedFeatures);
+ StatusWithMatchExpression s =
+ _parseComparison(name, new EqualityMatchExpression(), e, expCtx, allowedFeatures);
if (!s.isOK())
return s;
std::unique_ptr<NotMatchExpression> n = stdx::make_unique<NotMatchExpression>();
@@ -198,7 +191,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
}
case PathAcceptingKeyword::EQUALITY:
return _parseComparison(
- name, new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
+ name, new EqualityMatchExpression(), e, expCtx, allowedFeatures);
case PathAcceptingKeyword::IN_EXPR: {
if (e.type() != Array)
@@ -207,7 +200,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
Status s = temp->init(name);
if (!s.isOK())
return s;
- s = _parseInExpression(temp.get(), e.Obj(), collator, expCtx);
+ s = _parseInExpression(temp.get(), e.Obj(), expCtx);
if (!s.isOK())
return s;
return {std::move(temp)};
@@ -220,7 +213,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
Status s = temp->init(name);
if (!s.isOK())
return s;
- s = _parseInExpression(temp.get(), e.Obj(), collator, expCtx);
+ s = _parseInExpression(temp.get(), e.Obj(), expCtx);
if (!s.isOK())
return s;
@@ -306,10 +299,10 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
}
case PathAcceptingKeyword::ELEM_MATCH:
- return _parseElemMatch(name, e, collator, expCtx, allowedFeatures, topLevel);
+ return _parseElemMatch(name, e, expCtx, allowedFeatures, topLevel);
case PathAcceptingKeyword::ALL:
- return _parseAll(name, e, collator, expCtx, allowedFeatures, topLevel);
+ return _parseAll(name, e, expCtx, allowedFeatures, topLevel);
case PathAcceptingKeyword::WITHIN:
case PathAcceptingKeyword::GEO_INTERSECTS:
@@ -356,7 +349,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
str::stream() << "$_internalSchemaObjectMatch must be an object");
}
- auto parsedSubObjExpr = _parse(e.Obj(), collator, expCtx, allowedFeatures, topLevel);
+ auto parsedSubObjExpr = _parse(e.Obj(), expCtx, allowedFeatures, topLevel);
if (!parsedSubObjExpr.isOK()) {
return parsedSubObjExpr;
}
@@ -394,7 +387,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_MATCH_ARRAY_INDEX: {
- return _parseInternalSchemaMatchArrayIndex(name, e, collator);
+ return _parseInternalSchemaMatchArrayIndex(name, e, expCtx);
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_ALL_ELEM_MATCH_FROM_INDEX: {
@@ -443,7 +436,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
}
auto exprWithPlaceholder =
- ExpressionWithPlaceholder::parse(second.embeddedObject(), collator);
+ ExpressionWithPlaceholder::parse(second.embeddedObject(), expCtx);
if (!exprWithPlaceholder.isOK()) {
return exprWithPlaceholder.getStatus();
}
@@ -477,7 +470,6 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(
StatusWithMatchExpression MatchExpressionParser::_parse(
const BSONObj& obj,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -494,8 +486,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, allowedFeatures, childIsTopLevel);
+ Status s =
+ _parseTreeList(e.Obj(), temp.get(), expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -503,8 +495,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, allowedFeatures, childIsTopLevel);
+ Status s =
+ _parseTreeList(e.Obj(), temp.get(), expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -512,8 +504,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, allowedFeatures, childIsTopLevel);
+ Status s =
+ _parseTreeList(e.Obj(), temp.get(), expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(temp.release());
@@ -562,11 +554,11 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
if (!s.isOK())
return s;
// 'id' is collation-aware. 'ref' and 'db' are compared using binary comparison.
- eq->setCollator(str::equals("id", rest) ? collator : nullptr);
+ eq->setCollator(str::equals("id", rest) ? expCtx->getCollator() : nullptr);
root->add(eq.release());
} else if (mongoutils::str::equals("_internalSchemaAllowedProperties", rest)) {
- auto allowedProperties = _parseInternalSchemaAllowedProperties(e, collator);
+ auto allowedProperties = _parseInternalSchemaAllowedProperties(e, expCtx);
if (!allowedProperties.isOK()) {
return allowedProperties.getStatus();
}
@@ -574,11 +566,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
} else if (mongoutils::str::equals("_internalSchemaCond", rest)) {
auto condExpr =
_parseInternalSchemaFixedArityArgument<InternalSchemaCondMatchExpression>(
- InternalSchemaCondMatchExpression::kName,
- e,
- collator,
- expCtx,
- allowedFeatures);
+ InternalSchemaCondMatchExpression::kName, e, expCtx, allowedFeatures);
if (!condExpr.isOK()) {
return condExpr.getStatus();
}
@@ -590,7 +578,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
Status(ErrorCodes::TypeMismatch, "$_internalSchemaXor must be an array")};
auto xorExpr = stdx::make_unique<InternalSchemaXorMatchExpression>();
Status s = _parseTreeList(
- e.Obj(), xorExpr.get(), collator, expCtx, allowedFeatures, childIsTopLevel);
+ e.Obj(), xorExpr.get(), expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
root->add(xorExpr.release());
@@ -676,13 +664,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
}
if (_isExpressionDocument(e, false)) {
- Status s = _parseSub(e.fieldName(),
- e.Obj(),
- root.get(),
- collator,
- expCtx,
- allowedFeatures,
- childIsTopLevel);
+ Status s = _parseSub(
+ e.fieldName(), e.Obj(), root.get(), expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s;
continue;
@@ -697,7 +680,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
}
auto eq = _parseComparison(
- e.fieldName(), new EqualityMatchExpression(), e, collator, expCtx, allowedFeatures);
+ e.fieldName(), new EqualityMatchExpression(), e, expCtx, allowedFeatures);
if (!eq.isOK())
return eq;
@@ -716,7 +699,6 @@ StatusWithMatchExpression MatchExpressionParser::_parse(
Status MatchExpressionParser::_parseSub(const char* name,
const BSONObj& sub,
AndMatchExpression* root,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -752,8 +734,8 @@ Status MatchExpressionParser::_parseSub(const char* name,
BSONElement deep = j.next();
const bool childIsTopLevel = false;
- StatusWithMatchExpression s = _parseSubField(
- sub, root, name, deep, collator, expCtx, allowedFeatures, childIsTopLevel);
+ StatusWithMatchExpression s =
+ _parseSubField(sub, root, name, deep, expCtx, allowedFeatures, childIsTopLevel);
if (!s.isOK())
return s.getStatus();
@@ -909,9 +891,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseRegexDocument(const char*
Status MatchExpressionParser::_parseInExpression(
InMatchExpression* inExpression,
const BSONObj& theArray,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx) {
- inExpression->setCollator(collator);
+ inExpression->setCollator(expCtx->getCollator());
std::vector<BSONElement> equalities;
BSONObjIterator i(theArray);
while (i.more()) {
@@ -963,7 +944,6 @@ StatusWithMatchExpression MatchExpressionParser::_parseType(const char* name,
StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
const char* name,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -994,7 +974,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
// value case
AndMatchExpression theAnd;
- Status s = _parseSub("", obj, &theAnd, collator, expCtx, allowedFeatures, topLevel);
+ Status s = _parseSub("", obj, &theAnd, expCtx, allowedFeatures, topLevel);
if (!s.isOK())
return s;
@@ -1018,7 +998,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
// object case
- StatusWithMatchExpression subRaw = _parse(obj, collator, expCtx, allowedFeatures, topLevel);
+ StatusWithMatchExpression subRaw = _parse(obj, expCtx, allowedFeatures, topLevel);
if (!subRaw.isOK())
return subRaw;
std::unique_ptr<MatchExpression> sub = std::move(subRaw.getValue());
@@ -1041,7 +1021,6 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(
StatusWithMatchExpression MatchExpressionParser::_parseAll(
const char* name,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -1075,7 +1054,6 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(
const bool childIsTopLevel = false;
StatusWithMatchExpression inner = _parseElemMatch(name,
hopefullyElemMatchObj.firstElement(),
- collator,
expCtx,
allowedFeatures,
childIsTopLevel);
@@ -1105,7 +1083,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(
Status s = x->init(name, e);
if (!s.isOK())
return s;
- x->setCollator(collator);
+ x->setCollator(expCtx->getCollator());
myAnd->add(x.release());
}
}
@@ -1328,7 +1306,6 @@ template <class T>
StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityArgument(
StringData name,
const BSONElement& input,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures) {
constexpr auto arity = T::arity();
@@ -1359,7 +1336,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityA
}
const bool isTopLevel = false;
- auto subexpr = _parse(elem.embeddedObject(), collator, expCtx, allowedFeatures, isTopLevel);
+ auto subexpr = _parse(elem.embeddedObject(), expCtx, allowedFeatures, isTopLevel);
if (!subexpr.isOK()) {
return subexpr.getStatus();
}
@@ -1439,7 +1416,7 @@ StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> parseExprWithPlaceholder(
StringData exprWithPlaceholderFieldName,
StringData expressionName,
StringData expectedPlaceholder,
- const CollatorInterface* collator) {
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
auto exprWithPlaceholderElem = containingObject[exprWithPlaceholderFieldName];
if (!exprWithPlaceholderElem) {
return {ErrorCodes::FailedToParse,
@@ -1453,7 +1430,7 @@ StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> parseExprWithPlaceholder(
}
auto result =
- ExpressionWithPlaceholder::parse(exprWithPlaceholderElem.embeddedObject(), collator);
+ ExpressionWithPlaceholder::parse(exprWithPlaceholderElem.embeddedObject(), expCtx);
if (!result.isOK()) {
return result.getStatus();
}
@@ -1475,7 +1452,7 @@ StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> parseExprWithPlaceholder(
StatusWith<std::vector<InternalSchemaAllowedPropertiesMatchExpression::PatternSchema>>
parsePatternProperties(BSONElement patternPropertiesElem,
StringData expectedPlaceholder,
- const CollatorInterface* collator) {
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
if (!patternPropertiesElem) {
return {ErrorCodes::FailedToParse,
str::stream() << InternalSchemaAllowedPropertiesMatchExpression::kName
@@ -1508,7 +1485,7 @@ parsePatternProperties(BSONElement patternPropertiesElem,
"expression"_sd,
InternalSchemaAllowedPropertiesMatchExpression::kName,
expectedPlaceholder,
- collator);
+ expCtx);
if (!expressionWithPlaceholder.isOK()) {
return expressionWithPlaceholder.getStatus();
}
@@ -1570,7 +1547,9 @@ StatusWith<boost::container::flat_set<StringData>> parseProperties(BSONElement p
} // namespace
StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaMatchArrayIndex(
- const char* path, const BSONElement& elem, const CollatorInterface* collator) {
+ const char* path,
+ const BSONElement& elem,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
if (elem.type() != BSONType::Object) {
return {ErrorCodes::TypeMismatch,
str::stream() << InternalSchemaMatchArrayIndexMatchExpression::kName
@@ -1601,7 +1580,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaMatchArrayI
"expression"_sd,
InternalSchemaMatchArrayIndexMatchExpression::kName,
namePlaceholder.getValue(),
- collator);
+ expCtx);
if (!expressionWithPlaceholder.isOK()) {
return expressionWithPlaceholder.getStatus();
}
@@ -1616,7 +1595,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaMatchArrayI
}
StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaAllowedProperties(
- const BSONElement& elem, const CollatorInterface* collator) {
+ const BSONElement& elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
if (elem.type() != BSONType::Object) {
return {ErrorCodes::TypeMismatch,
str::stream() << InternalSchemaAllowedPropertiesMatchExpression::kName
@@ -1638,7 +1617,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaAllowedProp
}
auto patternProperties =
- parsePatternProperties(subobj["patternProperties"], namePlaceholder.getValue(), collator);
+ parsePatternProperties(subobj["patternProperties"], namePlaceholder.getValue(), expCtx);
if (!patternProperties.isOK()) {
return patternProperties.getStatus();
}
@@ -1647,7 +1626,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaAllowedProp
"otherwise"_sd,
InternalSchemaAllowedPropertiesMatchExpression::kName,
namePlaceholder.getValue(),
- collator);
+ expCtx);
if (!otherwise.isOK()) {
return otherwise.getStatus();
}
diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h
index 095bd79212d..44ffd4ae9a0 100644
--- a/src/mongo/db/matcher/expression_parser.h
+++ b/src/mongo/db/matcher/expression_parser.h
@@ -44,7 +44,6 @@
namespace mongo {
-class CollatorInterface;
class OperationContext;
enum class PathAcceptingKeyword {
@@ -123,18 +122,13 @@ public:
*/
static StatusWithMatchExpression parse(
const BSONObj& obj,
- const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
AllowedFeatureSet allowedFeatures = kDefaultSpecialFeatures) {
- // A non-null ExpressionContext is required for parsing $expr.
- if (!expCtx) {
- invariant((allowedFeatures & AllowedFeatures::kExpr) == 0u);
- }
-
+ invariant(expCtx.get());
const bool topLevelCall = true;
return MatchExpressionParser(&extensionsCallback)
- ._parse(obj, collator, expCtx, allowedFeatures, topLevelCall);
+ ._parse(obj, expCtx, allowedFeatures, topLevelCall);
}
/**
@@ -185,14 +179,10 @@ private:
/**
* Parse 'obj' and return either a MatchExpression or an error.
*
- * 'collator' is the collator that constructed collation-aware MatchExpressions will use. It
- * must outlive the returned MatchExpression and any clones made of it.
- *
* 'topLevel' indicates whether or not the we are at the top level of the tree across recursive
* class to this function. This is used to apply special logic at the top level.
*/
StatusWithMatchExpression _parse(const BSONObj& obj,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel);
@@ -205,7 +195,6 @@ private:
Status _parseSub(const char* name,
const BSONObj& obj,
AndMatchExpression* root,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel);
@@ -219,7 +208,6 @@ private:
const AndMatchExpression* andSoFar,
const char* name,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel);
@@ -228,7 +216,6 @@ private:
const char* name,
ComparisonMatchExpression* cmp,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures);
@@ -240,7 +227,6 @@ private:
Status _parseInExpression(InMatchExpression* entries,
const BSONObj& theArray,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx);
template <class T>
@@ -259,14 +245,12 @@ private:
StatusWithMatchExpression _parseElemMatch(const char* name,
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);
@@ -275,14 +259,12 @@ private:
Status _parseTreeList(const BSONObj& arr,
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);
@@ -307,7 +289,6 @@ private:
StatusWithMatchExpression _parseInternalSchemaFixedArityArgument(
StringData name,
const BSONElement& elem,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures);
@@ -331,10 +312,12 @@ private:
* Parses 'elem' into an InternalSchemaMatchArrayIndexMatchExpression.
*/
StatusWithMatchExpression _parseInternalSchemaMatchArrayIndex(
- const char* path, const BSONElement& elem, const CollatorInterface* collator);
+ const char* path,
+ const BSONElement& elem,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx);
StatusWithMatchExpression _parseInternalSchemaAllowedProperties(
- const BSONElement& elem, const CollatorInterface* collator);
+ const BSONElement& elem, const boost::intrusive_ptr<ExpressionContext>& expCtx);
// Performs parsing for the match extensions. We do not own this pointer - it has to live
// as long as the parser is active.
diff --git a/src/mongo/db/matcher/expression_parser_array_test.cpp b/src/mongo/db/matcher/expression_parser_array_test.cpp
index 23cef6b1180..8216c58f8ff 100644
--- a/src/mongo/db/matcher/expression_parser_array_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_array_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_array.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
namespace mongo {
@@ -46,8 +47,8 @@ using std::string;
TEST(MatchExpressionParserArrayTest, Size1) {
BSONObj query = BSON("x" << BSON("$size" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -58,8 +59,8 @@ TEST(MatchExpressionParserArrayTest, Size1) {
TEST(MatchExpressionParserArrayTest, SizeAsLong) {
BSONObj query = BSON("x" << BSON("$size" << 2LL));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -70,30 +71,30 @@ TEST(MatchExpressionParserArrayTest, SizeAsLong) {
TEST(MatchExpressionParserArrayTest, SizeAsNegativeLong) {
BSONObj query = BSON("x" << BSON("$size" << -2LL));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeAsString) {
BSONObj query = BSON("x" << BSON("$size"
<< "a"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithIntegralDouble) {
BSONObj query = BSON("x" << BSON("$size" << 2.0));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -104,29 +105,29 @@ TEST(MatchExpressionParserArrayTest, SizeWithIntegralDouble) {
TEST(MatchExpressionParserArrayTest, SizeWithNegativeIntegralDouble) {
BSONObj query = BSON("x" << BSON("$size" << -2.0));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithDouble) {
BSONObj query = BSON("x" << BSON("$size" << 2.5));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeWithNegative) {
BSONObj query = BSON("x" << BSON("$size" << -2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserArrayTest, SizeBad) {
BSONObj query = BSON("x" << BSON("$size" << BSONNULL));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
@@ -134,8 +135,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -147,8 +148,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchArr1) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -159,8 +160,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -172,8 +173,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchNor) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -184,8 +185,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchOr) {
TEST(MatchExpressionParserArrayTest, ElemMatchVal1) {
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("$gt" << 5)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -211,8 +212,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef1) {
<< "db");
BSONObj query = BSON("x" << BSON("$elemMatch" << BSON("$eq" << match)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -237,8 +238,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef2) {
<< "db");
BSONObj query = BSON("x" << BSON("$elemMatch" << match));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -264,8 +265,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef3) {
<< 12345);
BSONObj query = BSON("x" << BSON("$elemMatch" << match));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -307,8 +308,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef4) {
<< "db");
BSONObj query = BSON("x" << BSON("$elemMatch" << matchOutOfOrder));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -337,8 +338,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef5) {
<< 12345);
BSONObj query = BSON("x" << BSON("$elemMatch" << matchOutOfOrder));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -377,8 +378,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef6) {
<< 12345);
BSONObj query = BSON("x" << BSON("$elemMatch" << matchMissingID));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -415,8 +416,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef7) {
<< 12345);
BSONObj query = BSON("x" << BSON("$elemMatch" << matchMissingRef));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -459,8 +460,8 @@ TEST(MatchExpressionParserArrayTest, ElemMatchDBRef8) {
<< 12345);
BSONObj query = BSON("x" << BSON("$elemMatch" << matchDBOnly));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << match)));
@@ -482,8 +483,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -499,8 +500,8 @@ TEST(MatchExpressionParserArrayTest, All1) {
TEST(MatchExpressionParserArrayTest, AllNull) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(BSONNULL)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -514,8 +515,8 @@ TEST(MatchExpressionParserArrayTest, AllNull) {
TEST(MatchExpressionParserArrayTest, AllBadArg) {
BSONObj query = BSON("x" << BSON("$all" << 1));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
@@ -528,8 +529,8 @@ TEST(MatchExpressionParserArrayTest, AllBadRegexArg) {
BSONObj query = BSON("x" << operand.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
@@ -542,8 +543,8 @@ TEST(MatchExpressionParserArrayTest, AllRegex1) {
all.appendArray("$all", allArray.obj());
BSONObj query = BSON("a" << all.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -569,8 +570,8 @@ TEST(MatchExpressionParserArrayTest, AllRegex2) {
all.appendArray("$all", allArray.obj());
BSONObj query = BSON("a" << all.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -587,8 +588,8 @@ TEST(MatchExpressionParserArrayTest, AllRegex2) {
TEST(MatchExpressionParserArrayTest, AllNonArray) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(5)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to AND.
@@ -604,8 +605,8 @@ TEST(MatchExpressionParserArrayTest, AllNonArray) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to an AND with a single ELEM_MATCH_OBJECT child.
@@ -625,8 +626,8 @@ TEST(MatchExpressionParserArrayTest, AllElemMatch1) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
// Verify that the $all got parsed to an AND with a single ELEM_MATCH_OBJECT child.
@@ -661,8 +662,8 @@ TEST(MatchExpressionParserArrayTest, AllElemMatch2) {
// are correct.
TEST(MatchExpressionParserArrayTest, AllElemMatch3) {
BSONObj query = fromjson("{x: {$all: [{$elemMatch: {y: 1, z: 1}}]}}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
std::unique_ptr<MatchExpression> expr = std::move(result.getValue());
@@ -697,12 +698,12 @@ TEST(MatchExpressionParserArrayTest, AllElemMatchBad) {
BSONObj internal = BSON("x" << 1 << "y" << 2);
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(BSON("$elemMatch" << internal) << 5)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$all" << BSON_ARRAY(5 << BSON("$elemMatch" << internal))));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
@@ -710,31 +711,31 @@ TEST(MatchExpressionParserArrayTest, AllElemMatchBad) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result1 = MatchExpressionParser::parse(bad1, expCtx);
ASSERT_FALSE(result1.isOK());
// equality first, $elemMatch second
BSONObj bad2 = fromjson("{x: {$all: [3, {$elemMatch: {y: 1}}]}}");
- StatusWithMatchExpression result2 = MatchExpressionParser::parse(bad2, collator);
+ StatusWithMatchExpression result2 = MatchExpressionParser::parse(bad2, expCtx);
ASSERT_FALSE(result1.isOK());
// $elemMatch first, object second
BSONObj bad3 = fromjson("{x: {$all: [{$elemMatch: {y: 1}}, {z: 1}]}}");
- StatusWithMatchExpression result3 = MatchExpressionParser::parse(bad3, collator);
+ StatusWithMatchExpression result3 = MatchExpressionParser::parse(bad3, expCtx);
ASSERT_FALSE(result3.isOK());
// object first, $elemMatch second
BSONObj bad4 = fromjson("{x: {$all: [{z: 1}, {$elemMatch: {y: 1}}]}}");
- StatusWithMatchExpression result4 = MatchExpressionParser::parse(bad4, collator);
+ StatusWithMatchExpression result4 = MatchExpressionParser::parse(bad4, expCtx);
ASSERT_FALSE(result4.isOK());
}
// $all with empty string.
TEST(MatchExpressionParserArrayTest, AllEmptyString) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("")));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -758,8 +759,8 @@ TEST(MatchExpressionParserArrayTest, AllISODate) {
const Date_t& notMatch = notMatchResult.getValue();
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY(match)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << notMatch)));
@@ -774,8 +775,8 @@ TEST(MatchExpressionParserArrayTest, AllISODate) {
// $all on array element with empty string.
TEST(MatchExpressionParserArrayTest, AllDottedEmptyString) {
BSONObj query = BSON("x.1" << BSON("$all" << BSON_ARRAY("")));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -801,8 +802,8 @@ TEST(MatchExpressionParserArrayTest, AllDottedISODate) {
const Date_t& notMatch = notMatchResult.getValue();
BSONObj query = BSON("x.1" << BSON("$all" << BSON_ARRAY(match)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << notMatch)));
@@ -818,21 +819,23 @@ TEST(MatchExpressionParserArrayTest, AllDottedISODate) {
TEST(MatchExpressionParserArrayTest, AllStringNullCollation) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("string")));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::AND, result.getValue()->matchType());
ASSERT_EQUALS(1U, result.getValue()->numChildren());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::EQ, child->matchType());
EqualityMatchExpression* eqMatch = static_cast<EqualityMatchExpression*>(child);
- ASSERT_TRUE(eqMatch->getCollator() == collator);
+ ASSERT_TRUE(eqMatch->getCollator() == nullptr);
}
TEST(MatchExpressionParserArrayTest, AllStringCollation) {
BSONObj query = BSON("x" << BSON("$all" << BSON_ARRAY("string")));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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 38ffdafe4da..7410fb1b01a 100644
--- a/src/mongo/db/matcher/expression_parser_geo_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_geo_test.cpp
@@ -35,21 +35,16 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_geo.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
-#include "mongo/db/pipeline/aggregation_context_fixture.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
namespace mongo {
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,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(fromjson("{a: [3,4]}")));
@@ -64,14 +59,9 @@ TEST(MatchExpressionParserGeoNear, ParseNear) {
"{loc:{$near:{$maxDistance:100, "
"$geometry:{type:\"Point\", coordinates:[0,0]}}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- StatusWithMatchExpression result =
- MatchExpressionParser::parse(query,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -87,10 +77,8 @@ TEST(MatchExpressionParserGeoNear, ParseNearExtraField) {
"{loc:{$near:{$maxDistance:100, "
"$geometry:{type:\"Point\", coordinates:[0,0]}}, foo: 1}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -107,14 +95,9 @@ TEST(MatchExpressionParserGeoNear, ParseNearExtraField) {
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,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -128,11 +111,9 @@ TEST(MatchExpressionParserGeoNear, ParseValidNear) {
TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $near: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -140,11 +121,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $near: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -152,10 +131,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -164,10 +141,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $minDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -176,10 +151,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$near: [0,0], $eq: 40}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -188,11 +161,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$eq: 40, $near: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -201,10 +172,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
{
BSONObj query = fromjson(
"{loc: {$near: [0,0], $geoWithin: {$geometry: {type: \"Polygon\", coordinates: []}}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -213,11 +182,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$near: {$foo: 1}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -225,11 +192,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
}
{
BSONObj query = fromjson("{loc: {$minDistance: 10}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -240,14 +205,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNear) {
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,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -261,11 +221,9 @@ TEST(MatchExpressionParserGeoNear, ParseValidGeoNear) {
TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $geoNear: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -273,11 +231,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $geoNear: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -285,10 +241,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $eq: 1}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -297,10 +251,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $maxDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -309,10 +261,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
}
{
BSONObj query = fromjson("{loc: {$geoNear: [0,0], $minDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -324,14 +274,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidGeoNear) {
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,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
@@ -345,11 +290,9 @@ TEST(MatchExpressionParserGeoNear, ParseValidNearSphere) {
TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
{
BSONObj query = fromjson("{loc: {$maxDistance: 100, $nearSphere: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -357,11 +300,9 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
}
{
BSONObj query = fromjson("{loc: {$minDistance: 100, $nearSphere: [0,0]}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -369,10 +310,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $maxDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -381,10 +320,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $minDistance: {}}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
@@ -393,10 +330,8 @@ TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
}
{
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $eq: 1}}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_THROWS(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures)
diff --git a/src/mongo/db/matcher/expression_parser_leaf_test.cpp b/src/mongo/db/matcher/expression_parser_leaf_test.cpp
index 074825045b1..b327ba11d00 100644
--- a/src/mongo/db/matcher/expression_parser_leaf_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_leaf_test.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.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"
@@ -47,12 +48,12 @@ using std::string;
TEST(MatchExpressionParserLeafTest, NullCollation) {
BSONObj query = BSON("x"
<< "string");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -60,7 +61,9 @@ TEST(MatchExpressionParserLeafTest, Collation) {
BSONObj query = BSON("x"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -69,8 +72,8 @@ TEST(MatchExpressionParserLeafTest, Collation) {
TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
BSONObj query = BSON("x" << BSON("$eq" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -80,20 +83,20 @@ TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
TEST(MatchExpressionParserLeafTest, SimpleEQUndefined) {
BSONObj query = BSON("x" << BSON("$eq" << BSONUndefined));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, EQNullCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -101,7 +104,9 @@ TEST(MatchExpressionParserLeafTest, EQCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -110,8 +115,8 @@ TEST(MatchExpressionParserLeafTest, EQCollation) {
TEST(MatchExpressionParserLeafTest, SimpleGT1) {
BSONObj query = BSON("x" << BSON("$gt" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -121,12 +126,12 @@ TEST(MatchExpressionParserLeafTest, SimpleGT1) {
TEST(MatchExpressionParserLeafTest, GTNullCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -134,7 +139,9 @@ TEST(MatchExpressionParserLeafTest, GTCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get());
@@ -143,8 +150,8 @@ TEST(MatchExpressionParserLeafTest, GTCollation) {
TEST(MatchExpressionParserLeafTest, SimpleLT1) {
BSONObj query = BSON("x" << BSON("$lt" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -155,12 +162,12 @@ TEST(MatchExpressionParserLeafTest, SimpleLT1) {
TEST(MatchExpressionParserLeafTest, LTNullCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -168,7 +175,9 @@ TEST(MatchExpressionParserLeafTest, LTCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get());
@@ -177,8 +186,8 @@ TEST(MatchExpressionParserLeafTest, LTCollation) {
TEST(MatchExpressionParserLeafTest, SimpleGTE1) {
BSONObj query = BSON("x" << BSON("$gte" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -189,12 +198,12 @@ TEST(MatchExpressionParserLeafTest, SimpleGTE1) {
TEST(MatchExpressionParserLeafTest, GTENullCollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -202,7 +211,9 @@ TEST(MatchExpressionParserLeafTest, GTECollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get());
@@ -211,8 +222,8 @@ TEST(MatchExpressionParserLeafTest, GTECollation) {
TEST(MatchExpressionParserLeafTest, SimpleLTE1) {
BSONObj query = BSON("x" << BSON("$lte" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -223,12 +234,12 @@ TEST(MatchExpressionParserLeafTest, SimpleLTE1) {
TEST(MatchExpressionParserLeafTest, LTENullCollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
@@ -236,7 +247,9 @@ TEST(MatchExpressionParserLeafTest, LTECollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get());
@@ -245,8 +258,8 @@ TEST(MatchExpressionParserLeafTest, LTECollation) {
TEST(MatchExpressionParserLeafTest, SimpleNE1) {
BSONObj query = BSON("x" << BSON("$ne" << 2));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -257,14 +270,14 @@ TEST(MatchExpressionParserLeafTest, SimpleNE1) {
TEST(MatchExpressionParserLeafTest, NENullCollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::EQ, child->matchType());
EqualityMatchExpression* eqMatch = static_cast<EqualityMatchExpression*>(child);
- ASSERT_TRUE(eqMatch->getCollator() == collator);
+ ASSERT_TRUE(eqMatch->getCollator() == nullptr);
}
@@ -272,7 +285,9 @@ TEST(MatchExpressionParserLeafTest, NECollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -283,35 +298,35 @@ TEST(MatchExpressionParserLeafTest, NECollation) {
TEST(MatchExpressionParserLeafTest, SimpleModBad1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3)));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2 << 4)));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON_ARRAY("q" << 2)));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << 3));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$mod" << BSON("a" << 1 << "b" << 2)));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5)));
@@ -321,8 +336,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -335,19 +350,21 @@ TEST(MatchExpressionParserLeafTest, SimpleModNotNumber) {
TEST(MatchExpressionParserLeafTest, IdCollation) {
BSONObj query = BSON("$id"
<< "string");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
TEST(MatchExpressionParserLeafTest, IdNullCollation) {
BSONObj query = BSON("$id"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -358,7 +375,9 @@ TEST(MatchExpressionParserLeafTest, RefCollation) {
BSONObj query = BSON("$ref"
<< "coll");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -369,7 +388,9 @@ TEST(MatchExpressionParserLeafTest, DbCollation) {
BSONObj query = BSON("$db"
<< "db");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get());
@@ -378,8 +399,8 @@ TEST(MatchExpressionParserLeafTest, DbCollation) {
TEST(MatchExpressionParserLeafTest, SimpleIN1) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(2 << 3)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -389,18 +410,20 @@ TEST(MatchExpressionParserLeafTest, SimpleIN1) {
TEST(MatchExpressionParserLeafTest, INNullCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get());
- ASSERT_TRUE(match->getCollator() == collator);
+ ASSERT_TRUE(match->getCollator() == nullptr);
}
TEST(MatchExpressionParserLeafTest, INCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get());
@@ -415,8 +438,8 @@ TEST(MatchExpressionParserLeafTest, INSingleDBRef) {
<< oid
<< "$db"
<< "db"))));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -497,8 +520,8 @@ TEST(MatchExpressionParserLeafTest, INMultipleDBRef) {
<< oid
<< "$db"
<< "db"))));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -638,8 +661,8 @@ TEST(MatchExpressionParserLeafTest, INDBRefWithOptionalField1) {
<< oid
<< "foo"
<< 12345))));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
OID oidx = OID::gen();
@@ -673,23 +696,23 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) {
// missing $id
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"))));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
- result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
+ result = MatchExpressionParser::parse(query, expCtx);
// second field is not $id
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$foo"
<< 1))));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
// missing $id and $ref field
@@ -697,35 +720,35 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) {
<< "test"
<< "foo"
<< 3))));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, INNotArray) {
BSONObj query = BSON("x" << BSON("$in" << 5));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
@@ -736,16 +759,16 @@ TEST(MatchExpressionParserLeafTest, INRegexTooLong) {
BSONObjBuilder operand;
operand.appendArray("$in", inArray.obj());
BSONObj query = BSON("x" << operand.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
@@ -758,8 +781,8 @@ TEST(MatchExpressionParserLeafTest, INRegexStuff) {
operand.appendArray("$in", inArray.obj());
BSONObj query = BSON("a" << operand.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
BSONObj matchFirst = BSON("a"
@@ -784,8 +807,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -795,27 +818,29 @@ TEST(MatchExpressionParserLeafTest, SimpleNIN1) {
TEST(MatchExpressionParserLeafTest, NINNotArray) {
BSONObj query = BSON("x" << BSON("$nin" << 5));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::MATCH_IN, child->matchType());
InMatchExpression* inMatch = static_cast<InMatchExpression*>(child);
- ASSERT_TRUE(inMatch->getCollator() == collator);
+ ASSERT_TRUE(inMatch->getCollator() == nullptr);
}
TEST(MatchExpressionParserLeafTest, NINCollation) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, &collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
@@ -828,8 +853,8 @@ TEST(MatchExpressionParserLeafTest, Regex1) {
BSONObjBuilder b;
b.appendRegex("x", "abc", "i");
BSONObj query = b.obj();
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -845,8 +870,8 @@ TEST(MatchExpressionParserLeafTest, Regex2) {
<< "abc"
<< "$options"
<< "i"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -862,8 +887,8 @@ TEST(MatchExpressionParserLeafTest, Regex3) {
<< "i"
<< "$regex"
<< "abc"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -880,35 +905,35 @@ TEST(MatchExpressionParserLeafTest, RegexBad) {
<< "abc"
<< "$optionas"
<< "i"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
// $regex does not with numbers
query = BSON("x" << BSON("$regex" << 123));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$regex" << BSON_ARRAY("abc")));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$optionas"
<< "i"));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
query = BSON("x" << BSON("$options"
<< "i"));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) {
BSONObj query = BSON("x" << BSON("$regex"
<< "^a\\x00b"));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
const auto value = "a\0b"_sd;
@@ -921,8 +946,8 @@ TEST(MatchExpressionParserLeafTest, ExistsYes1) {
BSONObjBuilder b;
b.appendBool("$exists", true);
BSONObj query = BSON("x" << b.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -935,8 +960,8 @@ TEST(MatchExpressionParserLeafTest, ExistsNO1) {
BSONObjBuilder b;
b.appendBool("$exists", false);
BSONObj query = BSON("x" << b.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -947,8 +972,8 @@ TEST(MatchExpressionParserLeafTest, ExistsNO1) {
TEST(MatchExpressionParserLeafTest, Type1) {
BSONObj query = BSON("x" << BSON("$type" << String));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -958,8 +983,8 @@ TEST(MatchExpressionParserLeafTest, Type1) {
TEST(MatchExpressionParserLeafTest, Type2) {
BSONObj query = BSON("x" << BSON("$type" << (double)NumberDouble));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -968,8 +993,8 @@ TEST(MatchExpressionParserLeafTest, Type2) {
TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) {
BSONObj query = BSON("x" << BSON("$type" << 1.5));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -978,8 +1003,8 @@ TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) {
TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) {
BSONObj query = BSON("x" << BSON("$type" << mongo::NumberDecimal));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_FALSE(result.getValue()->matchesBSON(BSON("x" << 5.3)));
@@ -988,8 +1013,8 @@ TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) {
TEST(MatchExpressionParserLeafTest, TypeNull) {
BSONObj query = BSON("x" << BSON("$type" << jstNULL));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSONObj()));
@@ -1003,36 +1028,33 @@ TEST(MatchExpressionParserLeafTest, TypeBadType) {
BSONObjBuilder b;
b.append("$type", (JSTypeMax + 1));
BSONObj query = BSON("x" << b.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeBadString) {
- const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(
- 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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: null}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: true}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: {}}}}"), expCtx).getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- fromjson("{a: {$type: ObjectId('000000000000000000000000')}}"), collator)
+ fromjson("{a: {$type: ObjectId('000000000000000000000000')}}"), expCtx)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: []}}"), collator).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: []}}"), expCtx).getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeStringnameDouble) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumberDouble =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'double'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'double'}}"), expCtx);
ASSERT_OK(typeNumberDouble.getStatus());
TypeMatchExpression* tmeNumberDouble =
static_cast<TypeMatchExpression*>(typeNumberDouble.getValue().get());
@@ -1044,9 +1066,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameDouble) {
}
TEST(MatchExpressionParserLeafTest, TypeStringNameNumberDecimal) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumberDecimal =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'decimal'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'decimal'}}"), expCtx);
ASSERT_OK(typeNumberDecimal.getStatus());
TypeMatchExpression* tmeNumberDecimal =
static_cast<TypeMatchExpression*>(typeNumberDecimal.getValue().get());
@@ -1058,9 +1080,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringNameNumberDecimal) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberInt) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumberInt =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'int'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'int'}}"), expCtx);
ASSERT_OK(typeNumberInt.getStatus());
TypeMatchExpression* tmeNumberInt =
static_cast<TypeMatchExpression*>(typeNumberInt.getValue().get());
@@ -1072,9 +1094,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumberInt) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberLong) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumberLong =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'long'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'long'}}"), expCtx);
ASSERT_OK(typeNumberLong.getStatus());
TypeMatchExpression* tmeNumberLong =
static_cast<TypeMatchExpression*>(typeNumberLong.getValue().get());
@@ -1086,9 +1108,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumberLong) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameString) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeString =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'string'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'string'}}"), expCtx);
ASSERT_OK(typeString.getStatus());
TypeMatchExpression* tmeString = static_cast<TypeMatchExpression*>(typeString.getValue().get());
ASSERT_FALSE(tmeString->typeSet().allNumbers);
@@ -1099,9 +1121,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameString) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnamejstOID) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typejstOID =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'objectId'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'objectId'}}"), expCtx);
ASSERT_OK(typejstOID.getStatus());
TypeMatchExpression* tmejstOID = static_cast<TypeMatchExpression*>(typejstOID.getValue().get());
ASSERT_FALSE(tmejstOID->typeSet().allNumbers);
@@ -1112,9 +1134,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnamejstOID) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnamejstNULL) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typejstNULL =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'null'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'null'}}"), expCtx);
ASSERT_OK(typejstNULL.getStatus());
TypeMatchExpression* tmejstNULL =
static_cast<TypeMatchExpression*>(typejstNULL.getValue().get());
@@ -1126,9 +1148,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnamejstNULL) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameBool) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeBool =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'bool'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'bool'}}"), expCtx);
ASSERT_OK(typeBool.getStatus());
TypeMatchExpression* tmeBool = static_cast<TypeMatchExpression*>(typeBool.getValue().get());
ASSERT_FALSE(tmeBool->typeSet().allNumbers);
@@ -1139,9 +1161,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameBool) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameObject) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeObject =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'object'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'object'}}"), expCtx);
ASSERT_OK(typeObject.getStatus());
TypeMatchExpression* tmeObject = static_cast<TypeMatchExpression*>(typeObject.getValue().get());
ASSERT_FALSE(tmeObject->typeSet().allNumbers);
@@ -1152,9 +1174,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameObject) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameArray) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeArray =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'array'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'array'}}"), expCtx);
ASSERT_OK(typeArray.getStatus());
TypeMatchExpression* tmeArray = static_cast<TypeMatchExpression*>(typeArray.getValue().get());
ASSERT_FALSE(tmeArray->typeSet().allNumbers);
@@ -1165,9 +1187,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameArray) {
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumber) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: 'number'}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 'number'}}"), expCtx);
ASSERT_OK(typeNumber.getStatus());
TypeMatchExpression* tmeNumber = static_cast<TypeMatchExpression*>(typeNumber.getValue().get());
ASSERT_TRUE(tmeNumber->typeSet().allNumbers);
@@ -1179,9 +1201,9 @@ TEST(MatchExpressionParserLeafTest, TypeStringnameNumber) {
}
TEST(MatchExpressionParserLeafTest, CanParseArrayOfTypes) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: ['number', 2, 'object']}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: ['number', 2, 'object']}}"), expCtx);
ASSERT_OK(typeNumber.getStatus());
TypeMatchExpression* tme = static_cast<TypeMatchExpression*>(typeNumber.getValue().get());
ASSERT_TRUE(tme->typeSet().allNumbers);
@@ -1191,30 +1213,30 @@ TEST(MatchExpressionParserLeafTest, CanParseArrayOfTypes) {
}
TEST(MatchExpressionParserLeafTest, EmptyArrayFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: []}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: []}}"), expCtx);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeLessThanMinKeyFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: -20}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: -20}}"), expCtx);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeGreaterThanMaxKeyFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: 400}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 400}}"), expCtx);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeUnusedBetweenMinAndMaxFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression typeNumber =
- MatchExpressionParser::parse(fromjson("{a: {$type: 62}}"), collator);
+ MatchExpressionParser::parse(fromjson("{a: {$type: 62}}"), expCtx);
ASSERT_NOT_OK(typeNumber.getStatus());
}
@@ -1226,8 +1248,8 @@ TEST(MatchExpressionParserLeafTest, ValidTypeCodesParseSuccessfully) {
for (auto type : validTypes) {
BSONObj predicate = BSON("a" << BSON("$type" << type));
- const CollatorInterface* collator = nullptr;
- auto expression = MatchExpressionParser::parse(predicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expression = MatchExpressionParser::parse(predicate, expCtx);
ASSERT_OK(expression.getStatus());
auto typeExpression = static_cast<TypeMatchExpression*>(expression.getValue().get());
ASSERT_FALSE(typeExpression->typeSet().allNumbers);
@@ -1240,55 +1262,51 @@ TEST(MatchExpressionParserLeafTest, ValidTypeCodesParseSuccessfully) {
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidMask) {
const double k2Power53 = scalbn(1, 32);
- const CollatorInterface* collator = nullptr;
- ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << 54)), collator).getStatus());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
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)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << 54)), expCtx).getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<long long>::max())), expCtx)
.getStatus());
- ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53 - 1)), collator)
- .getStatus());
-
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << 54)), collator)
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53)), expCtx)
.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)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53 - 1)), expCtx)
.getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << 54)), collator).getStatus());
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << 54)), expCtx).getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<long long>::max())), collator)
+ BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<long long>::max())), expCtx)
.getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53)), collator)
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53)), expCtx)
.getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53 - 1)), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53 - 1)), expCtx)
.getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << 54)), collator)
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << 54)), expCtx).getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<long long>::max())), expCtx)
+ .getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53)), expCtx)
.getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<long long>::max())), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53 - 1)), expCtx)
.getStatus());
+
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << 54)), expCtx).getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53)), collator)
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<long long>::max())), expCtx)
.getStatus());
+ ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53)), expCtx)
+ .getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53 - 1)), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53 - 1)), expCtx)
.getStatus());
}
@@ -1299,392 +1317,391 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionValidArray) {
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[2].type());
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[3].type());
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0))), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << bsonArrayLongLong)),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- collator)
+ BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0 << 1 << 2 << 3))), expCtx)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << bsonArrayLongLong)), expCtx)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<int>::max()))), expCtx)
+ .getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0))), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
+ BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0 << 1 << 2 << 3))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << bsonArrayLongLong)),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0))), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << bsonArrayLongLong)),
- collator)
- .getStatus());
- ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- collator)
+ BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0 << 1 << 2 << 3))), expCtx)
.getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << bsonArrayLongLong)), expCtx)
+ .getStatus());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<int>::max()))), expCtx)
+ .getStatus());
ASSERT_OK(
- MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0))), collator)
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0 << 1 << 2 << 3))), collator)
+ BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0 << 1 << 2 << 3))), expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << bsonArrayLongLong)),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<int>::max()))),
- collator)
+ expCtx)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidBinData) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAllSet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAnySet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- collator)
+ expCtx)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
- collator)
+ expCtx)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskType) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: null}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: null}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: true}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: true}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: {}}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: {}}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ''}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ''}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: null}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: null}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: true}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: true}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {}}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {}}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ''}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ''}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- fromjson("{a: {$bitsAllClear: ObjectId('000000000000000000000000')}}"), collator)
+ fromjson("{a: {$bitsAllClear: ObjectId('000000000000000000000000')}}"), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: null}}"), collator).getStatus());
- ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: true}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: null}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {}}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: true}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ''}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {}}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(
- fromjson("{a: {$bitsAnySet: ObjectId('000000000000000000000000')}}"), collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ''}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(
+ fromjson("{a: {$bitsAnySet: ObjectId('000000000000000000000000')}}"), expCtx)
+ .getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: null}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: null}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: true}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: true}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {}}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {}}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ''}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ''}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- fromjson("{a: {$bitsAnyClear: ObjectId('000000000000000000000000')}}"), collator)
+ fromjson("{a: {$bitsAnyClear: ObjectId('000000000000000000000000')}}"), expCtx)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskValue) {
const double kLongLongMaxAsDouble = scalbn(1, std::numeric_limits<long long>::digits);
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: NaN}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: NaN}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: -54}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: -54}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<double>::max())), collator)
+ BSON("a" << BSON("$bitsAllSet" << std::numeric_limits<double>::max())), expCtx)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << kLongLongMaxAsDouble)), collator)
+ BSON("a" << BSON("$bitsAllSet" << kLongLongMaxAsDouble)), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: 2.5}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: 2.5}}"), expCtx).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllSet" << Decimal128("2.5"))), collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << Decimal128("2.5"))), expCtx)
+ .getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: NaN}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: NaN}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: -54}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: -54}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<double>::max())), collator)
+ BSON("a" << BSON("$bitsAllClear" << std::numeric_limits<double>::max())), expCtx)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << kLongLongMaxAsDouble)), collator)
+ BSON("a" << BSON("$bitsAllClear" << kLongLongMaxAsDouble)), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: 2.5}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: 2.5}}"), expCtx).getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAllClear" << Decimal128("2.5"))), collator)
+ BSON("a" << BSON("$bitsAllClear" << Decimal128("2.5"))), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: NaN}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: NaN}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: -54}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: -54}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<double>::max())), collator)
+ BSON("a" << BSON("$bitsAnySet" << std::numeric_limits<double>::max())), expCtx)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << kLongLongMaxAsDouble)), collator)
+ BSON("a" << BSON("$bitsAnySet" << kLongLongMaxAsDouble)), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: 2.5}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: 2.5}}"), expCtx).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnySet" << Decimal128("2.5"))), collator)
- .getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << Decimal128("2.5"))), expCtx)
+ .getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: NaN}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: NaN}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: -54}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: -54}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<double>::max())), collator)
+ BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits<double>::max())), expCtx)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << kLongLongMaxAsDouble)), collator)
+ BSON("a" << BSON("$bitsAnyClear" << kLongLongMaxAsDouble)), expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: 2.5}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: 2.5}}"), expCtx).getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
- BSON("a" << BSON("$bitsAnyClear" << Decimal128("2.5"))), collator)
+ BSON("a" << BSON("$bitsAnyClear" << Decimal128("2.5"))), expCtx)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArray) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [null]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [null]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [true]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [true]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ['']}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ['']}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{}]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{}]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [[]]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [[]]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllSet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- collator)
+ expCtx)
.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());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [null]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [{}]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [true]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [[]]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ['']}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1]}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [{}]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [[]]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [null]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [null]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [true]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [true]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ['']}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ['']}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [{}]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [{}]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [[]]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [[]]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnySet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- collator)
+ expCtx)
.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());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [null]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [{}]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [true]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [[]]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ['']}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1]}}"), collator).getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [{}]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [[]]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
- collator)
+ expCtx)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArrayValue) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-54]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-54]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [NaN]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [NaN]}}"), expCtx).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]}}"), collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [1e100]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1e100]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- collator)
+ expCtx)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-54]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [NaN]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [1e100]}}"), collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-54]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [NaN]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [1e100]}}"), expCtx)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1e100]}}"), collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1e100]}}"), expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-54]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-54]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
- MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [NaN]}}"), collator).getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [NaN]}}"), expCtx).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]}}"), collator)
- .getStatus());
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [1e100]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1e100]}}"), expCtx).getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- collator)
+ expCtx)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-54]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [NaN]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), collator)
- .getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [1e100]}}"), collator)
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-54]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [NaN]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"), expCtx).getStatus());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [1e100]}}"), expCtx)
.getStatus());
- ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1e100]}}"), collator)
+ ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1e100]}}"), expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<long long>::max()))),
- collator)
+ expCtx)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits<long long>::min()))),
- collator)
+ expCtx)
.getStatus());
}
} // namespace mongo
diff --git a/src/mongo/db/matcher/expression_parser_test.cpp b/src/mongo/db/matcher/expression_parser_test.cpp
index 9d9fe4d7856..ce520064261 100644
--- a/src/mongo/db/matcher/expression_parser_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_test.cpp
@@ -44,8 +44,8 @@ namespace mongo {
TEST(MatchExpressionParserTest, SimpleEQ1) {
BSONObj query = BSON("x" << 2);
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -54,8 +54,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 7)));
@@ -67,23 +67,23 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
query = BSON("x" << 5 << "$isolated" << 1);
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
query = BSON("x" << 5 << "y" << BSON("$isolated" << 1));
- result = MatchExpressionParser::parse(query, collator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserTest, MinDistanceWithoutNearFailsToParse) {
BSONObj query = fromjson("{loc: {$minDistance: 10}}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_FALSE(result.isOK());
}
@@ -227,25 +227,27 @@ TEST(StatusWithTest, Fib1) {
TEST(MatchExpressionParserTest, AlwaysFalseFailsToParseNonOneArguments) {
auto queryIntArgument = BSON(AlwaysFalseMatchExpression::kName << 0);
- auto expr = MatchExpressionParser::parse(queryIntArgument, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(queryIntArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON(AlwaysFalseMatchExpression::kName << "");
- expr = MatchExpressionParser::parse(queryStringArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryStringArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON(AlwaysFalseMatchExpression::kName << 1.1);
- expr = MatchExpressionParser::parse(queryDoubleArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON(AlwaysFalseMatchExpression::kName << true);
- expr = MatchExpressionParser::parse(queryFalseArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryFalseArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserTest, AlwaysFalseParsesIntegerArgument) {
auto query = BSON(AlwaysFalseMatchExpression::kName << 1);
- auto expr = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{}")));
@@ -255,25 +257,27 @@ TEST(MatchExpressionParserTest, AlwaysFalseParsesIntegerArgument) {
TEST(MatchExpressionParserTest, AlwaysTrueFailsToParseNonOneArguments) {
auto queryIntArgument = BSON(AlwaysTrueMatchExpression::kName << 0);
- auto expr = MatchExpressionParser::parse(queryIntArgument, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(queryIntArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON(AlwaysTrueMatchExpression::kName << "");
- expr = MatchExpressionParser::parse(queryStringArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryStringArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON(AlwaysTrueMatchExpression::kName << 1.1);
- expr = MatchExpressionParser::parse(queryDoubleArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON(AlwaysTrueMatchExpression::kName << true);
- expr = MatchExpressionParser::parse(queryFalseArgument, nullptr);
+ expr = MatchExpressionParser::parse(queryFalseArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserTest, AlwaysTrueParsesIntegerArgument) {
auto query = BSON(AlwaysTrueMatchExpression::kName << 1);
- auto expr = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{}")));
@@ -283,34 +287,29 @@ TEST(MatchExpressionParserTest, AlwaysTrueParsesIntegerArgument) {
TEST(MatchExpressionParserTest, TextFailsToParseWhenDisallowed) {
auto query = fromjson("{$text: {$search: 'str'}}");
- const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ query, 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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).getStatus());
}
TEST(MatchExpressionParserTest, WhereParsesSuccessfullyWhenAllowed) {
auto query = fromjson("{$where: 'this.a == this.b'}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatures::kJavascript)
@@ -319,16 +318,14 @@ TEST(MatchExpressionParserTest, WhereParsesSuccessfullyWhenAllowed) {
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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatures::kGeoNear)
@@ -337,16 +334,14 @@ TEST(MatchExpressionParserTest, NearSphereParsesSuccessfullyWhenAllowed) {
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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatures::kGeoNear)
@@ -355,16 +350,14 @@ TEST(MatchExpressionParserTest, GeoNearParsesSuccessfullyWhenAllowed) {
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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(MatchExpressionParser::parse(query,
- collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatures::kGeoNear)
@@ -373,43 +366,34 @@ TEST(MatchExpressionParserTest, NearParsesSuccessfullyWhenAllowed) {
TEST(MatchExpressionParserTest, ExprFailsToParseWhenDisallowed) {
auto query = fromjson("{$expr: {$eq: ['$a', 5]}}");
- const CollatorInterface* collator = nullptr;
- ASSERT_NOT_OK(MatchExpressionParser::parse(query, collator).getStatus());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(MatchExpressionParser::parse(query, expCtx).getStatus());
}
TEST(MatchExpressionParserTest, ExprParsesSuccessfullyWhenAllowed) {
auto query = fromjson("{$expr: {$eq: ['$a', 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());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::AllowedFeatures::kExpr)
+ .getStatus());
}
TEST(MatchExpressionParserTest, ExprParsesSuccessfullyWithAdditionalTopLevelPredicates) {
auto query = fromjson("{x: 1, $expr: {$eq: ['$a', 5]}, y: 1}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- ASSERT_OK(MatchExpressionParser::parse(query,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::AllowedFeatures::kExpr)
- .getStatus());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(
+ MatchExpressionParser::parse(
+ query, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::AllowedFeatures::kExpr)
+ .getStatus());
}
TEST(MatchExpressionParserTest, ExprFailsToParseWithinTopLevelOr) {
auto query = fromjson("{$or: [{x: 1}, {$expr: {$eq: ['$a', 5]}}]}");
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- ASSERT_NOT_OK(MatchExpressionParser::parse(query,
- collator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::AllowedFeatures::kExpr)
- .getStatus());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(
+ MatchExpressionParser::parse(
+ query, 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 58365df9ff6..3491d0ff734 100644
--- a/src/mongo/db/matcher/expression_parser_tree.cpp
+++ b/src/mongo/db/matcher/expression_parser_tree.cpp
@@ -41,7 +41,6 @@
namespace mongo {
Status MatchExpressionParser::_parseTreeList(const BSONObj& arr,
ListOfMatchExpression* out,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -55,8 +54,7 @@ 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, allowedFeatures, topLevel);
+ StatusWithMatchExpression sub = _parse(e.Obj(), expCtx, allowedFeatures, topLevel);
if (!sub.isOK())
return sub.getStatus();
@@ -68,7 +66,6 @@ Status MatchExpressionParser::_parseTreeList(const BSONObj& arr,
StatusWithMatchExpression MatchExpressionParser::_parseNot(
const char* name,
const BSONElement& e,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
AllowedFeatureSet allowedFeatures,
bool topLevel) {
@@ -91,8 +88,7 @@ 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, allowedFeatures, topLevel);
+ Status s = _parseSub(name, notObject, theAnd.get(), 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 d223a672c95..5047eee8448 100644
--- a/src/mongo/db/matcher/expression_parser_tree_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_tree_test.cpp
@@ -36,13 +36,14 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
+#include "mongo/db/pipeline/expression_context_for_test.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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -54,8 +55,8 @@ TEST(MatchExpressionParserTreeTest, OR1) {
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query2, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -67,8 +68,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -81,8 +82,8 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -93,8 +94,8 @@ TEST(MatchExpressionParserTreeTest, NOREmbedded) {
TEST(MatchExpressionParserTreeTest, NOT1) {
BSONObj query = BSON("x" << BSON("$not" << BSON("$gt" << 5)));
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
@@ -105,8 +106,8 @@ TEST(MatchExpressionParserLeafTest, NotRegex1) {
BSONObjBuilder b;
b.appendRegex("$not", "abc", "i");
BSONObj query = BSON("x" << b.obj());
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
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 1971087ed30..ca6e1ec0567 100644
--- a/src/mongo/db/matcher/expression_serialization_test.cpp
+++ b/src/mongo/db/matcher/expression_serialization_test.cpp
@@ -46,8 +46,6 @@ using std::pair;
using std::string;
using std::unique_ptr;
-constexpr CollatorInterface* kSimpleCollator = nullptr;
-
BSONObj serialize(MatchExpression* match) {
BSONObjBuilder bob;
match->serialize(&bob);
@@ -57,12 +55,10 @@ BSONObj serialize(MatchExpression* match) {
TEST(SerializeBasic, AndExpressionWithOneChildSerializesCorrectly) {
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);
@@ -79,12 +75,10 @@ TEST(SerializeBasic, AndExpressionWithOneChildSerializesCorrectly) {
TEST(SerializeBasic, AndExpressionWithTwoChildrenSerializesCorrectly) {
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);
@@ -101,12 +95,10 @@ TEST(SerializeBasic, AndExpressionWithTwoChildrenSerializesCorrectly) {
TEST(SerializeBasic, AndExpressionWithTwoIdenticalChildrenSerializesCorrectly) {
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);
@@ -123,12 +115,10 @@ TEST(SerializeBasic, AndExpressionWithTwoIdenticalChildrenSerializesCorrectly) {
TEST(SerializeBasic, ExpressionOr) {
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);
@@ -149,7 +139,6 @@ TEST(SerializeBasic, ExpressionOrWithNoChildrenSerializesCorrectly) {
// parser, since the parser does not permit a $or with no children.
OrMatchExpression original;
Matcher reserialized(serialize(&original),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -159,12 +148,10 @@ TEST(SerializeBasic, ExpressionOrWithNoChildrenSerializesCorrectly) {
TEST(SerializeBasic, ExpressionElemMatchObjectSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$elemMatch: {a: {$gt: 0}, b: {$gt: 0}}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -182,12 +169,10 @@ 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(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -205,12 +190,10 @@ 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(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -233,13 +216,9 @@ TEST(SerializeBasic, ExpressionElemMatchValueWithRegexSerializesCorrectly) {
<< "abc"
<< "$options"
<< "i")));
- Matcher original(match,
- kSimpleCollator,
- expCtx,
- ExtensionsCallbackNoop(),
- MatchExpressionParser::kAllowAllSpecialFeatures);
+ Matcher original(
+ match, expCtx, ExtensionsCallbackNoop(), MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -259,12 +238,10 @@ 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(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -284,12 +261,10 @@ TEST(SerializeBasic, ExpressionElemMatchValueWithEmptyStringSerializesCorrectly)
TEST(SerializeBasic, ExpressionSizeSerializesCorrectly) {
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);
@@ -306,12 +281,10 @@ TEST(SerializeBasic, ExpressionSizeSerializesCorrectly) {
TEST(SerializeBasic, ExpressionAllSerializesCorrectly) {
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);
@@ -328,12 +301,10 @@ TEST(SerializeBasic, ExpressionAllSerializesCorrectly) {
TEST(SerializeBasic, ExpressionAllWithEmptyArraySerializesCorrectly) {
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);
@@ -347,12 +318,10 @@ TEST(SerializeBasic, ExpressionAllWithEmptyArraySerializesCorrectly) {
TEST(SerializeBasic, ExpressionAllWithRegex) {
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);
@@ -374,12 +343,10 @@ TEST(SerializeBasic, ExpressionAllWithRegex) {
TEST(SerializeBasic, ExpressionEqSerializesCorrectly) {
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);
@@ -399,12 +366,10 @@ TEST(SerializeBasic, ExpressionEqSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNeSerializesCorrectly) {
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);
@@ -422,12 +387,10 @@ TEST(SerializeBasic, ExpressionNeWithRegexObjectSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(BSON("x" << BSON("$ne" << BSON("$regex"
<< "abc"))),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -446,12 +409,10 @@ TEST(SerializeBasic, ExpressionNeWithRegexObjectSerializesCorrectly) {
TEST(SerializeBasic, ExpressionLtSerializesCorrectly) {
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);
@@ -468,12 +429,10 @@ TEST(SerializeBasic, ExpressionLtSerializesCorrectly) {
TEST(SerializeBasic, ExpressionGtSerializesCorrectly) {
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);
@@ -490,12 +449,10 @@ TEST(SerializeBasic, ExpressionGtSerializesCorrectly) {
TEST(SerializeBasic, ExpressionGteSerializesCorrectly) {
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);
@@ -512,12 +469,10 @@ TEST(SerializeBasic, ExpressionGteSerializesCorrectly) {
TEST(SerializeBasic, ExpressionLteSerializesCorrectly) {
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);
@@ -534,12 +489,10 @@ TEST(SerializeBasic, ExpressionLteSerializesCorrectly) {
TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
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);
@@ -558,12 +511,10 @@ TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
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);
@@ -584,12 +535,10 @@ TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
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);
@@ -608,12 +557,10 @@ TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
TEST(SerializeBasic, ExpressionRegexWithEqObjSerializesCorrectly) {
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);
@@ -633,12 +580,10 @@ TEST(SerializeBasic, ExpressionRegexWithEqObjSerializesCorrectly) {
TEST(SerializeBasic, ExpressionModSerializesCorrectly) {
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);
@@ -655,12 +600,10 @@ TEST(SerializeBasic, ExpressionModSerializesCorrectly) {
TEST(SerializeBasic, ExpressionExistsTrueSerializesCorrectly) {
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);
@@ -677,12 +620,10 @@ TEST(SerializeBasic, ExpressionExistsTrueSerializesCorrectly) {
TEST(SerializeBasic, ExpressionExistsFalseSerializesCorrectly) {
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);
@@ -699,12 +640,10 @@ TEST(SerializeBasic, ExpressionExistsFalseSerializesCorrectly) {
TEST(SerializeBasic, ExpressionInSerializesCorrectly) {
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);
@@ -724,12 +663,10 @@ TEST(SerializeBasic, ExpressionInSerializesCorrectly) {
TEST(SerializeBasic, ExpressionInWithEmptyArraySerializesCorrectly) {
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);
@@ -743,12 +680,10 @@ TEST(SerializeBasic, ExpressionInWithEmptyArraySerializesCorrectly) {
TEST(SerializeBasic, ExpressionInWithRegexSerializesCorrectly) {
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);
@@ -768,12 +703,10 @@ TEST(SerializeBasic, ExpressionInWithRegexSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNinSerializesCorrectly) {
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);
@@ -793,12 +726,10 @@ TEST(SerializeBasic, ExpressionNinSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNinWithRegexValueSerializesCorrectly) {
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);
@@ -818,12 +749,10 @@ TEST(SerializeBasic, ExpressionNinWithRegexValueSerializesCorrectly) {
TEST(SerializeBasic, ExpressionBitsAllSetSerializesCorrectly) {
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);
@@ -840,12 +769,10 @@ TEST(SerializeBasic, ExpressionBitsAllSetSerializesCorrectly) {
TEST(SerializeBasic, ExpressionBitsAllClearSerializesCorrectly) {
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);
@@ -862,12 +789,10 @@ TEST(SerializeBasic, ExpressionBitsAllClearSerializesCorrectly) {
TEST(SerializeBasic, ExpressionBitsAnySetSerializesCorrectly) {
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);
@@ -884,12 +809,10 @@ TEST(SerializeBasic, ExpressionBitsAnySetSerializesCorrectly) {
TEST(SerializeBasic, ExpressionBitsAnyClearSerializesCorrectly) {
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);
@@ -909,12 +832,10 @@ TEST(SerializeBasic, ExpressionBitsAnyClearSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotSerializesCorrectly) {
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);
@@ -931,12 +852,10 @@ TEST(SerializeBasic, ExpressionNotSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotWithMultipleChildrenSerializesCorrectly) {
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);
@@ -954,12 +873,10 @@ TEST(SerializeBasic, ExpressionNotWithMultipleChildrenSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotWithBitTestSerializesCorrectly) {
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);
@@ -977,12 +894,10 @@ TEST(SerializeBasic, ExpressionNotWithBitTestSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotWithRegexObjSerializesCorrectly) {
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);
@@ -1001,12 +916,10 @@ TEST(SerializeBasic, ExpressionNotWithRegexObjSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotWithRegexValueSerializesCorrectly) {
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);
@@ -1025,12 +938,10 @@ TEST(SerializeBasic, ExpressionNotWithRegexValueSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNotWithRegexValueAndOptionsSerializesCorrectly) {
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);
@@ -1053,12 +964,10 @@ TEST(SerializeBasic, ExpressionNotWithGeoSerializesCorrectly) {
Matcher original(fromjson("{x: {$not: {$geoIntersects: {$geometry: {type: 'Polygon', "
"coordinates: [[[0,0], [5,0], "
"[5, 5], [0, 5], [0, 0]]]}}}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1086,12 +995,10 @@ TEST(SerializeBasic, ExpressionNotWithGeoSerializesCorrectly) {
TEST(SerializeBasic, ExpressionNorSerializesCorrectly) {
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);
@@ -1111,12 +1018,10 @@ TEST(SerializeBasic, ExpressionNorSerializesCorrectly) {
TEST(SerializeBasic, ExpressionTypeSerializesCorrectly) {
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);
@@ -1133,12 +1038,10 @@ TEST(SerializeBasic, ExpressionTypeSerializesCorrectly) {
TEST(SerializeBasic, ExpressionTypeWithNumberSerializesCorrectly) {
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);
@@ -1153,9 +1056,9 @@ TEST(SerializeBasic, ExpressionTypeWithNumberSerializesCorrectly) {
}
TEST(SerializeBasic, ExpressionTypeWithMultipleTypesSerializesCorrectly) {
- Matcher original(fromjson("{x: {$type: ['double', 'string', 'object', 'number']}}"),
- kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$type: ['double', 'string', 'object', 'number']}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$type: ['number', 1, 2, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -1170,8 +1073,9 @@ TEST(SerializeBasic, ExpressionTypeWithMultipleTypesSerializesCorrectly) {
}
TEST(SerializeInternalSchema, InternalSchemaTypeExpressionSerializesCorrectly) {
- Matcher original(fromjson("{x: {$_internalSchemaType: 2}}"), kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$_internalSchemaType: 2}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaType: [2]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -1183,8 +1087,9 @@ TEST(SerializeInternalSchema, InternalSchemaTypeExpressionSerializesCorrectly) {
}
TEST(SerializeInternalSchema, InternalSchemaTypeExpressionWithNumberSerializesCorrectly) {
- Matcher original(fromjson("{x: {$_internalSchemaType: 'number'}}"), kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$_internalSchemaType: 'number'}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$_internalSchemaType: ['number']}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -1197,10 +1102,10 @@ TEST(SerializeInternalSchema, InternalSchemaTypeExpressionWithNumberSerializesCo
}
TEST(SerializeInternalSchema, InternalSchemaTypeWithMultipleTypesSerializesCorrectly) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
- fromjson("{x: {$_internalSchemaType: ['double', 'string', 'object', 'number']}}"),
- kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ fromjson("{x: {$_internalSchemaType: ['double', 'string', 'object', 'number']}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
fromjson("{x: {$_internalSchemaType: ['number', 1, 2, 3]}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
@@ -1218,12 +1123,10 @@ TEST(SerializeInternalSchema, InternalSchemaTypeWithMultipleTypesSerializesCorre
TEST(SerializeBasic, ExpressionEmptySerializesCorrectly) {
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);
@@ -1237,12 +1140,10 @@ TEST(SerializeBasic, ExpressionEmptySerializesCorrectly) {
TEST(SerializeBasic, ExpressionWhereSerializesCorrectly) {
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);
@@ -1255,12 +1156,10 @@ 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(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1272,12 +1171,10 @@ TEST(SerializeBasic, ExpressionWhereWithScopeSerializesCorrectly) {
TEST(SerializeBasic, ExpressionExprSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$expr: {$eq: ['$a', 2]}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1295,12 +1192,10 @@ TEST(SerializeBasic, ExpressionExprSerializesCorrectly) {
TEST(SerializeBasic, ExpressionCommentSerializesCorrectly) {
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);
@@ -1320,12 +1215,10 @@ TEST(SerializeBasic, ExpressionGeoWithinSerializesCorrectly) {
fromjson(
"{x: {$geoWithin: {$geometry: "
"{type: 'Polygon', coordinates: [[[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]]]}}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1348,12 +1241,10 @@ TEST(SerializeBasic, ExpressionGeoIntersectsSerializesCorrectly) {
fromjson(
"{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[0,0], [5,0], [5, "
"5], [0, 5], [0, 0]]]}}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1382,12 +1273,10 @@ TEST(SerializeBasic, ExpressionNearSerializesCorrectly) {
Matcher original(
fromjson("{x: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}, $maxDistance: 10, "
"$minDistance: 1}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1404,12 +1293,10 @@ TEST(SerializeBasic, ExpressionNearSphereSerializesCorrectly) {
fromjson(
"{x: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}, $maxDistance: 10, "
"$minDistance: 1}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1423,12 +1310,10 @@ 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(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1441,12 +1326,10 @@ TEST(SerializeBasic, ExpressionTextSerializesCorrectly) {
TEST(SerializeBasic, ExpressionTextWithDefaultLanguageSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$text: {$search: 'a', $caseSensitive: false}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1459,12 +1342,10 @@ TEST(SerializeBasic, ExpressionTextWithDefaultLanguageSerializesCorrectly) {
TEST(SerializeBasic, ExpressionAlwaysTrueSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(BSON(AlwaysTrueMatchExpression::kName << 1),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1475,12 +1356,10 @@ TEST(SerializeBasic, ExpressionAlwaysTrueSerializesCorrectly) {
TEST(SerializeBasic, ExpressionAlwaysFalseSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(BSON(AlwaysFalseMatchExpression::kName << 1),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1491,12 +1370,10 @@ TEST(SerializeBasic, ExpressionAlwaysFalseSerializesCorrectly) {
TEST(SerializeInternalSchema, ExpressionInternalSchemaAllElemMatchFromIndexSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaAllElemMatchFromIndex: [2, {y: 1}]}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1507,12 +1384,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaAllElemMatchFromIndexSeria
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinItemsSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMinItems: 1}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1523,12 +1398,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMinItemsSerializesCorrectl
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxItemsSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMaxItems: 1}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1539,12 +1412,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxItemsSerializesCorrectl
TEST(SerializeInternalSchema, ExpressionInternalSchemaUniqueItemsSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaUniqueItems: true}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1556,12 +1427,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaUniqueItemsSerializesCorre
TEST(SerializeInternalSchema, ExpressionInternalSchemaObjectMatchSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaObjectMatch: {y: 1}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1572,12 +1441,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaObjectMatchSerializesCorre
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinLengthSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMinLength: 1}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1588,12 +1455,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMinLengthSerializesCorrect
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxLengthSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{x: {$_internalSchemaMaxLength: 1}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1604,12 +1469,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxLengthSerializesCorrect
TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$_internalSchemaCond: [{a: 1}, {b: 2}, {c: 3}]}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1623,12 +1486,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaCondSerializesCorrectly) {
TEST(SerializeInternalSchema, ExpressionInternalSchemaMinPropertiesSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$_internalSchemaMinProperties: 1}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1639,12 +1500,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMinPropertiesSerializesCor
TEST(SerializeInternalSchema, ExpressionInternalSchemaMaxPropertiesSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{$_internalSchemaMaxProperties: 1}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1656,12 +1515,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaFmodSerializesCorrectly) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(
fromjson("{a: {$_internalSchemaFmod: [NumberDecimal('2.3'), NumberDecimal('1.1')]}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1680,12 +1537,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaMatchArrayIndexSerializesC
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
Matcher original(fromjson("{a: {$_internalSchemaMatchArrayIndex:"
"{index: 2, namePlaceholder: 'i', expression: {i: {$lt: 3}}}}}"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1703,12 +1558,10 @@ TEST(SerializeInternalSchema, ExpressionInternalSchemaAllowedPropertiesSerialize
namePlaceholder: 'i',
patternProperties: [{regex: /b/, expression: {i: {$type: 'number'}}}]
}})"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1730,12 +1583,10 @@ TEST(SerializeInternalSchema,
namePlaceholder: 'i',
patternProperties: []
}})"),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
Matcher reserialized(serialize(original.getMatchExpression()),
- kSimpleCollator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
@@ -1749,16 +1600,18 @@ TEST(SerializeInternalSchema,
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaEqSerializesCorrectly) {
- Matcher original(fromjson("{x: {$_internalSchemaEq: {y: 1}}}"), kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{x: {$_internalSchemaEq: {y: 1}}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$_internalSchemaEq: {y: 1}}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
}
TEST(SerializeInternalSchema, ExpressionInternalSchemaRootDocEqSerializesCorrectly) {
- Matcher original(fromjson("{$_internalSchemaRootDocEq: {y: 1}}"), kSimpleCollator);
- Matcher reserialized(serialize(original.getMatchExpression()), kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher original(fromjson("{$_internalSchemaRootDocEq: {y: 1}}"), expCtx);
+ Matcher reserialized(serialize(original.getMatchExpression()), expCtx);
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$_internalSchemaRootDocEq: {y: 1}}"));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
diff --git a/src/mongo/db/matcher/expression_with_placeholder.cpp b/src/mongo/db/matcher/expression_with_placeholder.cpp
index 35f8cc1b2bb..cd68587b057 100644
--- a/src/mongo/db/matcher/expression_with_placeholder.cpp
+++ b/src/mongo/db/matcher/expression_with_placeholder.cpp
@@ -89,8 +89,8 @@ 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, collator);
+ BSONObj rawFilter, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
+ StatusWithMatchExpression statusWithFilter = MatchExpressionParser::parse(rawFilter, expCtx);
if (!statusWithFilter.isOK()) {
return statusWithFilter.getStatus();
diff --git a/src/mongo/db/matcher/expression_with_placeholder.h b/src/mongo/db/matcher/expression_with_placeholder.h
index 27047def6d2..a60b55c0bc2 100644
--- a/src/mongo/db/matcher/expression_with_placeholder.h
+++ b/src/mongo/db/matcher/expression_with_placeholder.h
@@ -51,7 +51,7 @@ public:
* ownership of 'rawFilter'.
*/
static StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> parse(
- BSONObj rawFilter, const CollatorInterface* collator);
+ BSONObj rawFilter, const boost::intrusive_ptr<ExpressionContext>& expCtx);
/**
* Construct a new ExpressionWithPlaceholder. 'filter' must point to a valid MatchExpression.
diff --git a/src/mongo/db/matcher/expression_with_placeholder_test.cpp b/src/mongo/db/matcher/expression_with_placeholder_test.cpp
index 1d717bb1f19..7bd19b12d00 100644
--- a/src/mongo/db/matcher/expression_with_placeholder_test.cpp
+++ b/src/mongo/db/matcher/expression_with_placeholder_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_always_boolean.h"
#include "mongo/db/matcher/expression_with_placeholder.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/unittest.h"
@@ -41,9 +42,9 @@ namespace {
using unittest::assertGet;
TEST(ExpressionWithPlaceholderTest, ParseBasic) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{i: 0}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "i");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{i: 0}")));
@@ -51,9 +52,9 @@ TEST(ExpressionWithPlaceholderTest, ParseBasic) {
}
TEST(ExpressionWithPlaceholderTest, ParseDottedField) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'i.a': 0, 'i.b': 1}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "i");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{i: {a: 0, b: 1}}")));
@@ -61,9 +62,9 @@ TEST(ExpressionWithPlaceholderTest, ParseDottedField) {
}
TEST(ExpressionWithPlaceholderTest, ParseLogicalQuery) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$and: [{i: {$gte: 0}}, {i: {$lte: 0}}]}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "i");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{i: 0}")));
@@ -71,9 +72,9 @@ TEST(ExpressionWithPlaceholderTest, ParseLogicalQuery) {
}
TEST(ExpressionWithPlaceholderTest, ParseElemMatch) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{i: {$elemMatch: {a: 0}}}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "i");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{i: [{a: 0}]}")));
@@ -82,8 +83,10 @@ TEST(ExpressionWithPlaceholderTest, ParseElemMatch) {
TEST(ExpressionWithPlaceholderTest, ParseCollation) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
auto rawFilter = fromjson("{i: 'abc'}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, &collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "i");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{i: 'cba'}")));
@@ -91,9 +94,9 @@ TEST(ExpressionWithPlaceholderTest, ParseCollation) {
}
TEST(ExpressionWithPlaceholderTest, ParseIdContainsNumbersAndCapitals) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{iA3: 0}");
- auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto filter = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(filter->getPlaceholder());
ASSERT_EQ(*filter->getPlaceholder(), "iA3");
ASSERT_TRUE(filter->getFilter()->matchesBSON(fromjson("{'iA3': 0}")));
@@ -101,250 +104,250 @@ TEST(ExpressionWithPlaceholderTest, ParseIdContainsNumbersAndCapitals) {
}
TEST(ExpressionWithPlaceholderTest, BadMatchExpressionFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$and: 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, EmptyMatchExpressionParsesSuccessfully) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{}");
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
}
TEST(ExpressionWithPlaceholderTest, NestedEmptyMatchExpressionParsesSuccessfully) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$or: [{$and: [{}]}]}");
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
}
TEST(ExpressionWithPlaceholderTest,
NestedMatchExpressionParsesSuccessfullyWhenSomeClausesHaveNoFieldName) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$or: [{$and: [{}]}, {i: 0}, {i: 1}, {$and: [{}]}]}");
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(result->getPlaceholder());
ASSERT_EQ(*result->getPlaceholder(), "i"_sd);
}
TEST(ExpressionWithPlaceholderTest, SuccessfullyParsesExpressionsWithTypeOther) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter =
fromjson("{a: {$_internalSchemaObjectMatch: {$_internalSchemaMinProperties: 5}}}");
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(result->getPlaceholder());
ASSERT_EQ(*result->getPlaceholder(), "a"_sd);
rawFilter = fromjson("{a: {$_internalSchemaType: 'string'}}");
- result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT(result->getPlaceholder());
ASSERT_EQ(*result->getPlaceholder(), "a"_sd);
rawFilter = fromjson("{$_internalSchemaMinProperties: 1}}");
- result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
rawFilter = fromjson("{$_internalSchemaCond: [{a: {$exists: true}}, {b: 1}, {c: 1}]}");
- result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
}
TEST(ExpressionWithPlaceholderTest, SuccessfullyParsesAlwaysTrue) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = BSON(AlwaysTrueMatchExpression::kName << 1);
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
}
TEST(ExpressionWithPlaceholderTest, SuccessfullyParsesAlwaysFalse) {
- constexpr CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = BSON(AlwaysFalseMatchExpression::kName << 1);
- auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, collator));
+ auto result = assertGet(ExpressionWithPlaceholder::parse(rawFilter, expCtx));
ASSERT_FALSE(result->getPlaceholder());
}
TEST(ExpressionWithPlaceholderTest, EmptyFieldNameFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'': 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, EmptyElemMatchFieldNameFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'': {$elemMatch: {a: 0}}}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, EmptyTopLevelFieldNameFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'.i': 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, MultipleTopLevelFieldsFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$and: [{i: 0}, {j: 0}]}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, SpecialCharactersInFieldNameFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'i&': 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, FieldNameStartingWithNumberFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'3i': 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, FieldNameStartingWithCapitalFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{'Ai': 0}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, TextSearchExpressionFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$text: {$search: 'search terms'}}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, WhereExpressionFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$where: 'sleep(100)'}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, GeoNearExpressionFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter =
fromjson("{i: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, ExprExpressionFailsToParse) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter = fromjson("{$expr: {$eq: ['$i', 5]}}");
- auto status = ExpressionWithPlaceholder::parse(rawFilter, collator);
+ auto status = ExpressionWithPlaceholder::parse(rawFilter, expCtx);
ASSERT_NOT_OK(status.getStatus());
}
TEST(ExpressionWithPlaceholderTest, EquivalentIfPlaceholderAndExpressionMatch) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{i: 5}}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{i: 5}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT_TRUE(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, EmptyMatchExpressionsAreEquivalent) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, NestedEmptyMatchExpressionsAreEquivalent) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{$or: [{$and: [{}]}]}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{$or: [{$and: [{}]}]}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, SameObjectMatchesAreEquivalent) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 =
fromjson("{a: {$_internalSchemaObjectMatch: {$_internalSchemaMaxProperties: 2}}}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 =
fromjson("{a: {$_internalSchemaObjectMatch: {$_internalSchemaMaxProperties: 2}}}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, AlwaysTruesAreEquivalent) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = BSON(AlwaysTrueMatchExpression::kName << 1);
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = BSON(AlwaysTrueMatchExpression::kName << 1);
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, NotEquivalentIfPlaceholderDoesNotMatch) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{i: {$type: 'array'}}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{j: {$type: 'array'}}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT_FALSE(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholder, NotEquivalentIfOnePlaceholderIsEmpty) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{i: 5}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT_FALSE(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
}
TEST(ExpressionWithPlaceholderTest, NotEquivalentIfExpressionDoesNotMatch) {
- constexpr auto collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto rawFilter1 = fromjson("{i: {$lte: 5}}");
- auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, collator);
+ auto expressionWithPlaceholder1 = ExpressionWithPlaceholder::parse(rawFilter1, expCtx);
ASSERT_OK(expressionWithPlaceholder1.getStatus());
auto rawFilter2 = fromjson("{i: {$gte: 5}}");
- auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, collator);
+ auto expressionWithPlaceholder2 = ExpressionWithPlaceholder::parse(rawFilter2, expCtx);
ASSERT_OK(expressionWithPlaceholder2.getStatus());
ASSERT_FALSE(expressionWithPlaceholder1.getValue()->equivalent(
expressionWithPlaceholder2.getValue().get()));
diff --git a/src/mongo/db/matcher/matcher.cpp b/src/mongo/db/matcher/matcher.cpp
index 5648a4f15d5..bea280d4d0b 100644
--- a/src/mongo/db/matcher/matcher.cpp
+++ b/src/mongo/db/matcher/matcher.cpp
@@ -42,13 +42,12 @@
namespace mongo {
Matcher::Matcher(const BSONObj& pattern,
- const CollatorInterface* collator,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback,
const MatchExpressionParser::AllowedFeatureSet allowedFeatures)
: _pattern(pattern) {
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- pattern, collator, expCtx, extensionsCallback, allowedFeatures);
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(pattern, 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 4d1c8783747..1e4fbd999c0 100644
--- a/src/mongo/db/matcher/matcher.h
+++ b/src/mongo/db/matcher/matcher.h
@@ -55,8 +55,7 @@ public:
* 'collator' must outlive the returned Matcher and any MatchExpression cloned from it.
*/
Matcher(const BSONObj& pattern,
- const CollatorInterface* collator,
- const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatureSet allowedFeatures =
MatchExpressionParser::kDefaultSpecialFeatures);
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 f21d80676f8..1d4fecbf366 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
@@ -32,24 +32,25 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
namespace {
-constexpr CollatorInterface* kSimpleCollator = nullptr;
-
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesEmptyQuery) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {}]}}");
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3 << 4))));
@@ -61,21 +62,24 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchesValidQueries) {
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, RejectsNonArrayElements) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(
expr.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << BSON_ARRAY(3 << 4) << 4))));
@@ -87,7 +91,8 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, NestedArraysMatchSubexp
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchedQueriesWithDottedPaths) {
auto query = fromjson("{'a.b': {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(
expr.getValue()->matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3 << 4)))));
@@ -95,7 +100,8 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, MatchedQueriesWithDotte
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, HasSingleChild) {
auto query = fromjson("{'a.b': {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->numChildren(), 1U);
@@ -106,7 +112,8 @@ DEATH_TEST(InternalSchemaAllElemMatchFromIndexMatchExpression,
GetChildFailsIndexGreaterThanOne,
"Invariant failure i == 0") {
auto query = fromjson("{'a.b': {$_internalSchemaAllElemMatchFromIndex: [2, {a: {$lt: 5}}]}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
objMatch.getValue()->getChild(1);
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 01dac629ea1..e0956999840 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
@@ -31,17 +31,18 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
-constexpr auto kSimpleCollator = nullptr;
TEST(InternalSchemaAllowedPropertiesMatchExpression, MatchesObjectsWithListedProperties) {
auto filter = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a', 'b'],"
"namePlaceholder: 'i', patternProperties: [], otherwise: {i: 0}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: 1, b: 1}")));
@@ -60,7 +61,8 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, MatchesObjectsWithMatchingP
],
otherwise: {i: {$type: 'string'}}
}})");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{puppies: 2, kittens: 3, phoneNum: 1234}")));
@@ -73,7 +75,8 @@ 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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: 6}")));
@@ -92,7 +95,8 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, OtherwiseEnforcedWhenApprop
],
otherwise: {i: {$type: 'string'}}
}})");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: 'bar'}")));
@@ -103,7 +107,8 @@ 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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
auto clone = expr.getValue()->shallowClone();
ASSERT_TRUE(expr.getValue()->equivalent(clone.get()));
@@ -111,7 +116,7 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, EquivalentToClone) {
filter = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [], otherwise: {}}}");
- expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
clone = expr.getValue()->shallowClone();
ASSERT_TRUE(expr.getValue()->equivalent(clone.get()));
@@ -121,7 +126,8 @@ TEST(InternalSchemaAllowedPropertiesMatchExpression, HasCorrectNumberOfChilden)
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a'], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {i: 1}}], otherwise: {i: 7}}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->numChildren(), 2U);
@@ -134,7 +140,8 @@ DEATH_TEST(InternalSchemaAllowedPropertiesMatchExpression,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['a'], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {i: 1}}], otherwise: {i: 7}}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
const size_t numChildren = 2;
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 b1cbb03d18a..f1a022da7c4 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
@@ -32,6 +32,7 @@
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/schema/expression_internal_schema_cond.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -44,12 +45,12 @@ std::unique_ptr<InternalSchemaCondMatchExpression> createCondMatchExpression(BSO
BSONObj elseBranch) {
auto cond = stdx::make_unique<InternalSchemaCondMatchExpression>();
- const CollatorInterface* kSimpleCollator = nullptr;
- auto conditionExpr = MatchExpressionParser::parse(condition, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto conditionExpr = MatchExpressionParser::parse(condition, expCtx);
ASSERT_OK(conditionExpr.getStatus());
- auto thenBranchExpr = MatchExpressionParser::parse(thenBranch, kSimpleCollator);
+ auto thenBranchExpr = MatchExpressionParser::parse(thenBranch, expCtx);
ASSERT_OK(thenBranchExpr.getStatus());
- auto elseBranchExpr = MatchExpressionParser::parse(elseBranch, kSimpleCollator);
+ auto elseBranchExpr = MatchExpressionParser::parse(elseBranch, expCtx);
cond->init({{std::move(conditionExpr.getValue()),
std::move(thenBranchExpr.getValue()),
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
index f82f0b34bf0..3ccc5175092 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_eq.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -118,26 +119,28 @@ TEST(InternalSchemaEqMatchExpression, EquivalentReturnsCorrectResults) {
{a: {$_internalSchemaEq: {
b: {c: 1, d: 1}
}}})");
- Matcher eqExpr(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher eqExpr(query, expCtx);
query = fromjson(R"(
{a: {$_internalSchemaEq: {
b: {d: 1, c: 1}
}}})");
- Matcher eqExprEq(query, nullptr);
+ Matcher eqExprEq(query, expCtx);
ASSERT_TRUE(eqExpr.getMatchExpression()->equivalent(eqExprEq.getMatchExpression()));
query = fromjson(R"(
{a: {$_internalSchemaEq: {
b: {d: 1}
}}})");
- Matcher eqExprNotEq(query, nullptr);
+ Matcher eqExprNotEq(query, expCtx);
ASSERT_FALSE(eqExpr.getMatchExpression()->equivalent(eqExprNotEq.getMatchExpression()));
}
TEST(InternalSchemaEqMatchExpression, EquivalentToClone) {
auto query = fromjson("{a: {$_internalSchemaEq: {a:1, b: {c: 1, d: [1]}}}}");
- Matcher rootDocEq(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher rootDocEq(query, expCtx);
auto clone = rootDocEq.getMatchExpression()->shallowClone();
ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(clone.get()));
}
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 fcceda2f0d3..cc2c51e3dce 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
@@ -32,19 +32,20 @@
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/expression_with_placeholder.h"
#include "mongo/db/matcher/schema/expression_internal_schema_match_array_index.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
namespace {
-constexpr auto kSimpleCollator = nullptr;
TEST(InternalSchemaMatchArrayIndexMatchExpression, RejectsNonArrays) {
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$gt: 7}}}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: 'blah'}")));
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: 7}")));
@@ -55,7 +56,8 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesArraysWithMatchingElem
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$elemMatch: {'bar': 7}}}}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
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}]]}")));
@@ -63,7 +65,7 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesArraysWithMatchingElem
filter = fromjson(
"{baz: {$_internalSchemaMatchArrayIndex:"
"{index: 2, namePlaceholder: 'i', expression: {i: {$type: 'string'}}}}}");
- expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{baz: [0, 1, '2']}")));
}
@@ -72,14 +74,15 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, DoesNotMatchArrayIfMatchingEl
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$lte: 7}}}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
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, kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{foo: [0, 99, 1, 2]}")));
}
@@ -88,14 +91,15 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, MatchesIfNotEnoughArrayElemen
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: 1}}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
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, kSimpleCollator);
+ expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{foo: ['no', 'no', 'no', 'no']}")));
}
@@ -104,7 +108,8 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, EquivalentToClone) {
auto filter = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}");
- auto expr = MatchExpressionParser::parse(filter, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(filter, expCtx);
ASSERT_OK(expr.getStatus());
auto clone = expr.getValue()->shallowClone();
ASSERT_TRUE(expr.getValue()->equivalent(clone.get()));
@@ -114,7 +119,8 @@ TEST(InternalSchemaMatchArrayIndexMatchExpression, HasSingleChild) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->numChildren(), 1U);
@@ -127,7 +133,8 @@ DEATH_TEST(InternalSchemaMatchArrayIndexMatchExpression,
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$type: 'number'}}}}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
objMatch.getValue()->getChild(1);
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 22137895c3d..a6d0ff5b5f9 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
@@ -31,6 +31,7 @@
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -40,7 +41,8 @@ namespace mongo {
namespace {
TEST(InternalSchemaObjectMatchExpression, RejectsNonObjectElements) {
- auto subExpr = MatchExpressionParser::parse(BSON("b" << 1), nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto subExpr = MatchExpressionParser::parse(BSON("b" << 1), expCtx);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -53,9 +55,10 @@ TEST(InternalSchemaObjectMatchExpression, RejectsNonObjectElements) {
}
TEST(InternalSchemaObjectMatchExpression, RejectsObjectsThatDontMatch) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto subExpr = MatchExpressionParser::parse(BSON("b" << BSON("$type"
<< "string")),
- nullptr);
+ expCtx);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -66,9 +69,10 @@ TEST(InternalSchemaObjectMatchExpression, RejectsObjectsThatDontMatch) {
}
TEST(InternalSchemaObjectMatchExpression, AcceptsObjectsThatMatch) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto subExpr = MatchExpressionParser::parse(BSON("b" << BSON("$type"
<< "string")),
- nullptr);
+ expCtx);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -87,9 +91,10 @@ TEST(InternalSchemaObjectMatchExpression, AcceptsObjectsThatMatch) {
}
TEST(InternalSchemaObjectMatchExpression, DottedPathAcceptsObjectsThatMatch) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto subExpr = MatchExpressionParser::parse(BSON("b.c.d" << BSON("$type"
<< "string")),
- nullptr);
+ expCtx);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -103,7 +108,8 @@ TEST(InternalSchemaObjectMatchExpression, DottedPathAcceptsObjectsThatMatch) {
}
TEST(InternalSchemaObjectMatchExpression, EmptyMatchAcceptsAllObjects) {
- auto subExpr = MatchExpressionParser::parse(BSONObj(), nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto subExpr = MatchExpressionParser::parse(BSONObj(), expCtx);
ASSERT_OK(subExpr.getStatus());
InternalSchemaObjectMatchExpression objMatch;
@@ -125,7 +131,8 @@ TEST(InternalSchemaObjectMatchExpression, NestedObjectMatchReturnsCorrectPath) {
" $or: [{c: {$type: 'string'}}, {c: {$gt: 0}}]"
" }}}"
" }}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->path(), "a");
@@ -139,7 +146,8 @@ TEST(InternalSchemaObjectMatchExpression, MatchesNestedObjectMatch) {
" c: 3"
" }}}"
" }}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_FALSE(objMatch.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -153,31 +161,34 @@ TEST(InternalSchemaObjectMatchExpression, EquivalentReturnsCorrectResults) {
" {a: {$_internalSchemaObjectMatch: {"
" b: 3"
" }}}");
- Matcher objectMatch(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher objectMatch(query, expCtx);
query = fromjson(
" {a: {$_internalSchemaObjectMatch: {"
" b: {$eq: 3}"
" }}}");
- Matcher objectMatchEq(query, nullptr);
+ Matcher objectMatchEq(query, expCtx);
ASSERT_TRUE(objectMatch.getMatchExpression()->equivalent(objectMatchEq.getMatchExpression()));
query = fromjson(
" {a: {$_internalSchemaObjectMatch: {"
" c: {$eq: 3}"
" }}}");
- Matcher objectMatchNotEq(query, nullptr);
+ Matcher objectMatchNotEq(query, expCtx);
ASSERT_FALSE(
objectMatch.getMatchExpression()->equivalent(objectMatchNotEq.getMatchExpression()));
}
TEST(InternalSchemaObjectMatchExpression, SubExpressionRespectsCollator) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
auto query = fromjson(
"{a: {$_internalSchemaObjectMatch: {"
" b: {$eq: 'FOO'}"
"}}}");
- auto objectMatch = MatchExpressionParser::parse(query, &collator);
+ auto objectMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objectMatch.getStatus());
ASSERT_TRUE(objectMatch.getValue()->matchesBSON(fromjson("{a: {b: 'FOO'}}")));
@@ -187,7 +198,8 @@ TEST(InternalSchemaObjectMatchExpression, SubExpressionRespectsCollator) {
TEST(InternalSchemaObjectMatchExpression, RejectsArraysContainingMatchingSubObject) {
auto query = fromjson("{a: {$_internalSchemaObjectMatch: {b: 1}}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_FALSE(objMatch.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -201,7 +213,8 @@ TEST(InternalSchemaObjectMatchExpression, HasSingleChild) {
" {a: {$_internalSchemaObjectMatch: {"
" c: {$eq: 3}"
" }}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
ASSERT_EQ(objMatch.getValue()->numChildren(), 1U);
@@ -215,7 +228,8 @@ DEATH_TEST(InternalSchemaObjectMatchExpression,
" {a: {$_internalSchemaObjectMatch: {"
" c: {$eq: 3}"
" }}}");
- auto objMatch = MatchExpressionParser::parse(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto objMatch = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(objMatch.getStatus());
objMatch.getValue()->getChild(1);
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
index 4b46779b173..ade721236d3 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/bson/json.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -92,26 +93,28 @@ TEST(InternalSchemaRootDocEqMatchExpression, EquivalentReturnsCorrectResults) {
{$_internalSchemaRootDocEq: {
b: 1, c: 1
}})");
- Matcher rootDocEq(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher rootDocEq(query, expCtx);
query = fromjson(R"(
{$_internalSchemaRootDocEq: {
c: 1, b: 1
}})");
- Matcher exprEq(query, nullptr);
+ Matcher exprEq(query, expCtx);
ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(exprEq.getMatchExpression()));
query = fromjson(R"(
{$_internalSchemaRootDocEq: {
c: 1
}})");
- Matcher exprNotEq(query, nullptr);
+ Matcher exprNotEq(query, expCtx);
ASSERT_FALSE(rootDocEq.getMatchExpression()->equivalent(exprNotEq.getMatchExpression()));
}
TEST(InternalSchemaRootDocEqMatchExpression, EquivalentToClone) {
auto query = fromjson("{$_internalSchemaRootDocEq: {a:1, b: {c: 1, d: [1]}}}");
- Matcher rootDocEq(query, nullptr);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ Matcher rootDocEq(query, expCtx);
auto clone = rootDocEq.getMatchExpression()->shallowClone();
ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(clone.get()));
}
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 37f6ff4f6c2..60d7e4d90e8 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
@@ -34,6 +34,7 @@
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/matcher/schema/expression_internal_schema_xor.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -48,8 +49,8 @@ TEST(InternalSchemaXorOp, MatchesNothingWhenHasNoClauses) {
TEST(InternalSchemaXorOp, MatchesSingleClause) {
BSONObj matchPredicate = fromjson("{$_internalSchemaXor: [{a: { $ne: 5 }}]}");
- const CollatorInterface* collator = nullptr;
- auto expr = MatchExpressionParser::parse(matchPredicate, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << 4)));
@@ -59,11 +60,11 @@ TEST(InternalSchemaXorOp, MatchesSingleClause) {
}
TEST(InternalSchemaXorOp, MatchesThreeClauses) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BSONObj matchPredicate =
fromjson("{$_internalSchemaXor: [{a: { $gt: 10 }}, {a: { $lt: 0 }}, {b: 0}]}");
- auto expr = MatchExpressionParser::parse(matchPredicate, collator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(BSON("a" << -1)));
@@ -77,11 +78,11 @@ TEST(InternalSchemaXorOp, MatchesThreeClauses) {
}
TEST(InternalSchemaXorOp, DoesNotUseElemMatchKey) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BSONObj matchPredicate = fromjson("{$_internalSchemaXor: [{a: 1}, {b: 2}]}");
- auto expr = MatchExpressionParser::parse(matchPredicate, collator);
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
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 ac6fb95f42b..ff3aa8beac4 100644
--- a/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_parser_schema_test.cpp
@@ -38,17 +38,17 @@
#include "mongo/db/matcher/schema/expression_internal_schema_min_length.h"
#include "mongo/db/matcher/schema/expression_internal_schema_object_match.h"
#include "mongo/db/matcher/schema/expression_internal_schema_unique_items.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
namespace {
-constexpr CollatorInterface* kSimpleCollator = nullptr;
-
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -59,7 +59,8 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -70,7 +71,8 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -81,7 +83,8 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDoubleArgumentAsInt
TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinItems" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -92,7 +95,8 @@ TEST(MatchExpressionParserSchemaTest, MinItemsCorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -103,7 +107,8 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -115,7 +120,8 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -126,7 +132,8 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDoubleArgumentAsInt
TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxItems" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
@@ -137,26 +144,28 @@ TEST(MatchExpressionParserSchemaTest, MaxItemsCorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, UniqueItemsFailsToParseNonTrueArguments) {
auto queryIntArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << 0));
- auto expr = MatchExpressionParser::parse(queryIntArgument, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(queryIntArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaUniqueItems"
<< ""));
- expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryStringArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << 1.0));
- expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaUniqueItems" << false));
- expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, UniqueItemsParsesTrueBooleanArgument) {
auto query = BSON("x" << BSON("$_internalSchemaUniqueItems" << true));
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_FALSE(expr.getValue()->matchesBSON(fromjson("{x: 1}")));
@@ -170,17 +179,18 @@ TEST(MatchExpressionParserSchemaTest, UniqueItemsParsesTrueBooleanArgument) {
TEST(MatchExpressionParserSchemaTest, ObjectMatchOnlyAcceptsAnObjectArgument) {
auto query = BSON("a" << BSON("$_internalSchemaObjectMatch" << 1));
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
query = BSON("a" << BSON("$_internalSchemaObjectMatch"
<< "string"));
- result = MatchExpressionParser::parse(query, kSimpleCollator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
query = BSON(
"a" << BSON("$_internalSchemaObjectMatch" << BSON_ARRAY(BSON("a" << 1) << BSON("b" << 1))));
- result = MatchExpressionParser::parse(query, kSimpleCollator);
+ result = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse);
}
@@ -190,7 +200,8 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchCorrectlyParsesObjects) {
" b: {$gte: 0}"
" }}"
"}");
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT_FALSE(result.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -207,7 +218,8 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchCorrectlyParsesNestedObjectMatc
" $or: [{c: {$type: 'string'}}, {c: {$gt: 0}}]"
" }}"
"}}}");
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_TRUE(result.isOK());
ASSERT_FALSE(result.getValue()->matchesBSON(fromjson("{a: 1}")));
@@ -224,7 +236,8 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchSubExprRejectsTopLevelOperators
"{a: {$_internalSchemaObjectMatch: {"
" $isolated: 1"
"}}}");
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(result.getStatus(), ErrorCodes::BadValue);
}
@@ -233,7 +246,8 @@ TEST(MatchExpressionParserSchemaTest, ObjectMatchSubExprRejectsTopLevelOperators
//
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -246,7 +260,8 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -259,7 +274,8 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -272,7 +288,8 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDoubleArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMinLength" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
@@ -286,24 +303,25 @@ TEST(MatchExpressionParserSchemaTest, MinLengthCorrectlyParsesDecimalArgumentAsI
TEST(MatchExpressionParserSchemaTest, MinLengthFailsToParseNonIntegerArguments) {
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaMinLength"
<< "abc"));
- auto expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(queryStringArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryEmptyStringArgument = BSON("x" << BSON("$_internalSchemaMinLength"
<< ""));
- expr = MatchExpressionParser::parse(queryEmptyStringArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryEmptyStringArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaMinLength" << 1.5));
- expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaMinLength" << false));
- expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryArrArgument = BSON("x" << BSON("$_internalSchemaMinLength" << BSON_ARRAY(1)));
- expr = MatchExpressionParser::parse(queryArrArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryArrArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
}
@@ -312,7 +330,8 @@ TEST(MatchExpressionParserSchemaTest, MinLengthFailsToParseNonIntegerArguments)
//
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesIntegerArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -325,7 +344,8 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesIntegerArgument) {
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesLongArgument) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2LL));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -338,7 +358,8 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesLongArgument) {
TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesDoubleArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << 2.0));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -351,7 +372,8 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthCorrectlyParsesDoubleArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxLengthorrectlyParsesDecimalArgumentAsInteger) {
BSONObj query = BSON("x" << BSON("$_internalSchemaMaxLength" << Decimal128("2")));
- StatusWithMatchExpression result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT(result.getValue()->matchesBSON(BSON("x"
@@ -365,62 +387,66 @@ TEST(MatchExpressionParserSchemaTest, MaxLengthorrectlyParsesDecimalArgumentAsIn
TEST(MatchExpressionParserSchemaTest, MaxLengthFailsToParseNonIntegerArguments) {
auto queryStringArgument = BSON("x" << BSON("$_internalSchemaMaxLength"
<< "abc"));
- auto expr = MatchExpressionParser::parse(queryStringArgument, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(queryStringArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryEmptyStringArgument = BSON("x" << BSON("$_internalSchemaMaxLength"
<< ""));
- expr = MatchExpressionParser::parse(queryEmptyStringArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryEmptyStringArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryDoubleArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << 1.5));
- expr = MatchExpressionParser::parse(queryDoubleArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryDoubleArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryFalseArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << false));
- expr = MatchExpressionParser::parse(queryFalseArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryFalseArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
auto queryArrArgument = BSON("x" << BSON("$_internalSchemaMaxLength" << BSON_ARRAY(1)));
- expr = MatchExpressionParser::parse(queryArrArgument, kSimpleCollator);
+ expr = MatchExpressionParser::parse(queryArrArgument, expCtx);
ASSERT_NOT_OK(expr.getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondFailsToParseNonObjectArguments) {
auto queryWithInteger = fromjson("{$_internalSchemaCond: [1, {foo: 'bar'}, {baz: 7}]}");
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryWithInteger, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryWithInteger, expCtx).getStatus());
auto queryWithArray = fromjson("{$_internalSchemaCond: [{foo: 'bar'}, [{qux: 3}], {baz: 7}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryWithArray, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryWithArray, expCtx).getStatus());
auto queryWithString = fromjson("{$_internalSchemaCond: [{foo: 'bar'}, {baz: 7}, 'blah']}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryWithString, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryWithString, expCtx).getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondFailsToParseIfNotExactlyThreeArguments) {
auto queryNoArguments = fromjson("{$_internalSchemaCond: []}");
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryNoArguments, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryNoArguments, expCtx).getStatus());
auto queryOneArgument = fromjson("{$_internalSchemaCond: [{height: 171}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryOneArgument, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryOneArgument, expCtx).getStatus());
auto queryFourArguments = fromjson(
"{$_internalSchemaCond: [{make: 'lamborghini'}, {model: 'ghost'}, {color: 'celadon'}, "
"{used: false}]}");
ASSERT_EQ(ErrorCodes::FailedToParse,
- MatchExpressionParser::parse(queryFourArguments, kSimpleCollator).getStatus());
+ MatchExpressionParser::parse(queryFourArguments, expCtx).getStatus());
}
TEST(MatchExpressionParserSchemaTest, CondParsesThreeMatchExpresssions) {
auto query = fromjson(
"{$_internalSchemaCond: [{climate: 'rainy'}, {clothing: 'jacket'}, {clothing: 'shirt'}]}");
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(
@@ -434,79 +460,73 @@ TEST(MatchExpressionParserSchemaTest, CondParsesThreeMatchExpresssions) {
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseNonObjectArguments) {
auto query = fromjson("{foo: {$_internalSchemaMatchArrayIndex: 7}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson("{foo: {$_internalSchemaMatchArrayIndex: []}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"[{index: 5, namePlaceholder: 'i', expression: {i: 1}}]}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfPlaceholderNotValid) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 5, namePlaceholder: 7, expression: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 5, namePlaceholder: 'Z', expression: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfIndexNotANonnegativeInteger) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 'blah', namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: -1, namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 3.14, namePlaceholder: 'i', expression: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexFailsToParseIfExpressionNotValid) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: 'blah'}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {doesntMatchThePlaceholder: 7}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {$invalid: 'blah'}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, MatchArrayIndexParsesSuccessfully) {
auto query = fromjson(
"{foo: {$_internalSchemaMatchArrayIndex:"
"{index: 0, namePlaceholder: 'i', expression: {i: {$lt: 0}}}}}");
- auto matchArrayIndex = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto matchArrayIndex = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(matchArrayIndex.getStatus());
ASSERT_TRUE(matchArrayIndex.getValue()->matchesBSON(fromjson("{foo: [-1, 0, 1]}")));
@@ -517,32 +537,37 @@ TEST(MatchExpressionParserSchemaTest, MatchArrayIndexParsesSuccessfully) {
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithNegativeIndex) {
BSONObj matchPredicate =
fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [-2, {a: { $lt: 0 }}]}}");
- auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::TypeMismatch);
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithNonObjectExpression) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [-2, 4]}}");
- auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::TypeMismatch);
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithInvalidExpression) {
BSONObj matchPredicate =
fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [-2, {$fakeExpression: 4}]}}");
- auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::TypeMismatch);
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, FailsToParseWithEmptyArray) {
BSONObj matchPredicate = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: []}}");
- auto expr = MatchExpressionParser::parse(matchPredicate, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(matchPredicate, expCtx);
ASSERT_EQ(expr.getStatus(), ErrorCodes::FailedToParse);
}
TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, ParsesCorreclyWithValidInput) {
auto query = fromjson("{a: {$_internalSchemaAllElemMatchFromIndex: [2, {a: { $lt: 4 }}]}}");
- auto expr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto expr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(expr.getStatus());
ASSERT_TRUE(expr.getValue()->matchesBSON(fromjson("{a: [5, 3, 3, 3, 3, 3]}")));
@@ -551,14 +576,16 @@ TEST(InternalSchemaAllElemMatchFromIndexMatchExpression, ParsesCorreclyWithValid
TEST(MatchExpressionParserSchemaTest, InternalTypeFailsToParseOnTypeMismatch) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType" << BSONObj()));
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseNumberAlias) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType"
<< "number"));
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -569,7 +596,8 @@ TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseNumberAlias) {
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongAlias) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType"
<< "long"));
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -581,7 +609,8 @@ TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongAlias) {
TEST(MatchExpressionParserSchemaTest, InternalTypeCanParseLongCode) {
BSONObj query = BSON("x" << BSON("$_internalSchemaType" << 18));
- auto result = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto result = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(result.getStatus());
ASSERT_EQ(result.getValue()->matchType(), MatchExpression::INTERNAL_SCHEMA_TYPE);
@@ -595,68 +624,62 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfAFieldIsMis
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: []}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfNamePlaceholderNotAString) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 7, patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: /i/, patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfNamePlaceholderNotValid) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'Capital',"
"patternProperties: [], otherwise: {Capital: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::BadValue);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::BadValue);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: '', patternProperties: [], otherwise: {'': 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::BadValue);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfPropertiesNotAllStrings) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [7], namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: ['x', {}], namePlaceholder: 'i',"
"patternProperties: [], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -664,14 +687,13 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: ['blah'], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 1}, patternProperties: [{regex: /a/, expression: {i: 0}}, 'blah']}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -679,14 +701,13 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{foo: 1, bar: 1}], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, blah: 0}], otherwise: {i: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest,
@@ -694,20 +715,18 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{expression: {i: 0}}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: 7, expression: {i: 0}}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: 'notARegex', expression: {i: 0}}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -715,14 +734,13 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/, expression: 'blah'}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest,
@@ -730,44 +748,42 @@ TEST(MatchExpressionParserSchemaTest,
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"otherwise: {i: 0}, patternProperties: [{regex: /a/i, expression: {i: 0}}]}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::BadValue);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfMismatchingNamePlaceholders) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {j: 1}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [{regex: /a/, expression: {w: 7}}], otherwise: {i: 'foo'}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::FailedToParse);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::FailedToParse);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfOtherwiseIncorrectType) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: false}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: [{i: 7}]}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::TypeMismatch);
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesFailsParsingIfOtherwiseNotAValidExpression) {
auto query = fromjson(
"{$_internalSchemaAllowedProperties: {properties: [], namePlaceholder: 'i',"
"patternProperties: [], otherwise: {i: {$invalid: 1}}}}}}");
- ASSERT_EQ(MatchExpressionParser::parse(query, kSimpleCollator).getStatus(),
- ErrorCodes::BadValue);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_EQ(MatchExpressionParser::parse(query, expCtx).getStatus(), ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, AllowedPropertiesParsesSuccessfully) {
@@ -775,7 +791,8 @@ 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, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto allowedProperties = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(allowedProperties.getStatus());
ASSERT_TRUE(allowedProperties.getValue()->matchesBSON(
@@ -792,7 +809,8 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesAcceptsEmptyPropertiesAnd
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {i: 1}}}}");
- auto allowedProperties = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto allowedProperties = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(allowedProperties.getStatus());
ASSERT_TRUE(allowedProperties.getValue()->matchesBSON(BSONObj()));
@@ -802,7 +820,8 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesAcceptsEmptyOtherwiseExpr
auto query = fromjson(
"{$_internalSchemaAllowedProperties:"
"{properties: [], namePlaceholder: 'i', patternProperties: [], otherwise: {}}}}}");
- auto allowedProperties = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto allowedProperties = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(allowedProperties.getStatus());
ASSERT_TRUE(allowedProperties.getValue()->matchesBSON(BSONObj()));
@@ -810,7 +829,8 @@ TEST(MatchExpressionParserSchemaTest, AllowedPropertiesAcceptsEmptyOtherwiseExpr
TEST(MatchExpressionParserSchemaTest, EqParsesSuccessfully) {
auto query = fromjson("{foo: {$_internalSchemaEq: 1}}");
- auto eqExpr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto eqExpr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(eqExpr.getStatus());
ASSERT_TRUE(eqExpr.getValue()->matchesBSON(fromjson("{foo: 1}")));
@@ -820,31 +840,34 @@ TEST(MatchExpressionParserSchemaTest, EqParsesSuccessfully) {
TEST(MatchExpressionParserSchemaTest, RootDocEqFailsToParseNonObjects) {
auto query = fromjson("{$_internalSchemaRootDocEq: 1}");
- auto rootDocEq = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto rootDocEq = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(rootDocEq.getStatus(), ErrorCodes::TypeMismatch);
query = fromjson("{$_internalSchemaRootDocEq: [{}]}");
- rootDocEq = MatchExpressionParser::parse(query, kSimpleCollator);
+ rootDocEq = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(rootDocEq.getStatus(), ErrorCodes::TypeMismatch);
}
TEST(MatchExpressionParserSchemaTest, RootDocEqMustBeTopLevel) {
auto query = fromjson("{a: {$_internalSchemaRootDocEq: 1}}");
- auto rootDocEq = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto rootDocEq = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(rootDocEq.getStatus(), ErrorCodes::BadValue);
query = fromjson("{$or: [{a: 1}, {$_internalSchemaRootDocEq: 1}]}");
- rootDocEq = MatchExpressionParser::parse(query, kSimpleCollator);
+ rootDocEq = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(rootDocEq.getStatus(), ErrorCodes::FailedToParse);
query = fromjson("{a: {$elemMatch: {$_internalSchemaRootDocEq: 1}}}");
- rootDocEq = MatchExpressionParser::parse(query, kSimpleCollator);
+ rootDocEq = MatchExpressionParser::parse(query, expCtx);
ASSERT_EQ(rootDocEq.getStatus(), ErrorCodes::BadValue);
}
TEST(MatchExpressionParserSchemaTest, RootDocEqParsesSuccessfully) {
auto query = fromjson("{$_internalSchemaRootDocEq: {}}");
- auto eqExpr = MatchExpressionParser::parse(query, kSimpleCollator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ auto eqExpr = MatchExpressionParser::parse(query, expCtx);
ASSERT_OK(eqExpr.getStatus());
ASSERT_TRUE(eqExpr.getValue()->matchesBSON(fromjson("{}")));
diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript
index beadfc36549..c0ced70109d 100644
--- a/src/mongo/db/ops/SConscript
+++ b/src/mongo/db/ops/SConscript
@@ -50,116 +50,31 @@ env.Library(
)
env.CppUnitTest(
- target='modifier_add_to_set_test',
- source='modifier_add_to_set_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_bit_test',
- source='modifier_bit_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_compare_test',
- source='modifier_compare_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
+ target='modifier_update_test',
+ source=[
+ 'modifier_add_to_set_test.cpp',
+ 'modifier_bit_test.cpp',
+ 'modifier_compare_test.cpp',
+ 'modifier_current_date_test.cpp',
+ 'modifier_inc_test.cpp',
+ 'modifier_pop_test.cpp',
+ 'modifier_pull_all_test.cpp',
+ 'modifier_pull_test.cpp',
+ 'modifier_push_test.cpp',
+ 'modifier_rename_test.cpp',
+ 'modifier_set_test.cpp',
+ 'modifier_unset_test.cpp',
],
-)
-
-env.CppUnitTest(
- target='modifier_current_date_test',
- source='modifier_current_date_test.cpp',
LIBDEPS=[
'$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
+ '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/db/service_context_noop_init',
'$BUILD_DIR/mongo/db/logical_clock',
'update',
],
)
-env.CppUnitTest(
- target='modifier_inc_test',
- source='modifier_inc_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_pop_test',
- source='modifier_pop_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_pull_all_test',
- source='modifier_pull_all_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_pull_test',
- source='modifier_pull_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_push_test',
- source='modifier_push_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_rename_test',
- source='modifier_rename_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_set_test',
- source='modifier_set_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
-env.CppUnitTest(
- target='modifier_unset_test',
- source='modifier_unset_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
- 'update',
- ],
-)
-
env.Library(
target='write_ops_parsers',
source=[
diff --git a/src/mongo/db/ops/modifier_add_to_set.cpp b/src/mongo/db/ops/modifier_add_to_set.cpp
index acf34b2f544..32016419151 100644
--- a/src/mongo/db/ops/modifier_add_to_set.cpp
+++ b/src/mongo/db/ops/modifier_add_to_set.cpp
@@ -169,7 +169,7 @@ Status ModifierAddToSet::init(const BSONElement& modExpr, const Options& opts, b
_val = each;
}
- setCollator(opts.collator);
+ setCollator(opts.expCtx->getCollator());
return Status::OK();
}
diff --git a/src/mongo/db/ops/modifier_add_to_set_test.cpp b/src/mongo/db/ops/modifier_add_to_set_test.cpp
index e24515d1d56..68fe447dbbd 100644
--- a/src/mongo/db/ops/modifier_add_to_set_test.cpp
+++ b/src/mongo/db/ops/modifier_add_to_set_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -44,6 +45,7 @@ namespace {
using mongo::BSONObj;
using mongo::CollatorInterfaceMock;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierAddToSet;
using mongo::ModifierInterface;
@@ -59,7 +61,8 @@ public:
Mod() : _mod() {}
explicit Mod(BSONObj modObj,
- ModifierInterface::Options options = ModifierInterface::Options::normal())
+ ModifierInterface::Options options =
+ ModifierInterface::Options::normal(new ExpressionContextForTest()))
: _modObj(modObj), _mod() {
ASSERT_OK(_mod.init(_modObj["$addToSet"].embeddedObject().firstElement(), options));
}
@@ -401,9 +404,11 @@ TEST(Deduplication, ExistingDuplicatesArePreservedWithRespectToCollation) {
TEST(Collation, AddToSetRespectsCollationFromModifierOptions) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
Document doc(fromjson("{ a : ['not'] }"));
Mod mod(fromjson("{ $addToSet : { a : 'equal' } }"),
- ModifierInterface::Options::normal(&collator));
+ ModifierInterface::Options::normal(expCtx));
ModifierInterface::ExecInfo execInfo;
ASSERT_OK(mod.prepare(doc.root(), "", &execInfo));
diff --git a/src/mongo/db/ops/modifier_bit_test.cpp b/src/mongo/db/ops/modifier_bit_test.cpp
index 3c8fed4330e..204e2bd16a6 100644
--- a/src/mongo/db/ops/modifier_bit_test.cpp
+++ b/src/mongo/db/ops/modifier_bit_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/platform/decimal128.h"
#include "mongo/unittest/unittest.h"
@@ -44,6 +45,7 @@ namespace {
using mongo::BSONObj;
using mongo::Decimal128;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierBit;
using mongo::ModifierInterface;
@@ -61,7 +63,7 @@ public:
explicit Mod(BSONObj modObj) : _modObj(modObj), _mod() {
ASSERT_OK(_mod.init(_modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -89,50 +91,51 @@ private:
TEST(Init, FailToInitWithInvalidValue) {
BSONObj modObj;
ModifierBit mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
// Double is an invalid $bit argument
modObj = fromjson("{ $bit : { a : 0 } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// String is an invalid $bit argument
modObj = fromjson("{ $bit : { a : '' } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Array is an invalid $bit argument
modObj = fromjson("{ $bit : { a : [] } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An empty document is an invalid $bit argument.
modObj = fromjson("{$bit: {a: {}}}");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with value not in ('and', 'or') is an invalid $bit argument
modObj = fromjson("{ $bit : { a : { foo : 4 } } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// The argument to the sub-operator must be numeric
modObj = fromjson("{ $bit : { a : { or : [] } } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{ $bit : { a : { or : 'foo' } } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// The argument to the sub-operator must be integral
modObj = fromjson("{ $bit : { a : { or : 1.0 } } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// The argument to the sub-operator must be integral
modObj = fromjson("{ $bit : { a : { or : NumberDecimal(\"1.0\") } } }");
ASSERT_NOT_OK(mod.init(modObj["$bit"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, ParsesAndInt) {
diff --git a/src/mongo/db/ops/modifier_compare.cpp b/src/mongo/db/ops/modifier_compare.cpp
index 5f579e65cc6..a63d224a94f 100644
--- a/src/mongo/db/ops/modifier_compare.cpp
+++ b/src/mongo/db/ops/modifier_compare.cpp
@@ -84,7 +84,7 @@ Status ModifierCompare::init(const BSONElement& modExpr, const Options& opts, bo
// Store value for later.
_val = modExpr;
- _collator = opts.collator;
+ _collator = opts.expCtx->getCollator();
return Status::OK();
}
diff --git a/src/mongo/db/ops/modifier_compare_test.cpp b/src/mongo/db/ops/modifier_compare_test.cpp
index c454e741368..839697c899a 100644
--- a/src/mongo/db/ops/modifier_compare_test.cpp
+++ b/src/mongo/db/ops/modifier_compare_test.cpp
@@ -35,6 +35,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -43,6 +44,7 @@ namespace {
using mongo::BSONObj;
using mongo::CollatorInterfaceMock;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierCompare;
using mongo::ModifierInterface;
@@ -62,7 +64,8 @@ public:
Mod() : _mod() {}
explicit Mod(BSONObj modObj,
- ModifierInterface::Options options = ModifierInterface::Options::normal())
+ ModifierInterface::Options options =
+ ModifierInterface::Options::normal(new ExpressionContextForTest()))
: _modObj(modObj),
_mod((modObj.firstElement().fieldNameStringData() == "$min") ? ModifierCompare::MIN
: ModifierCompare::MAX) {
@@ -94,18 +97,19 @@ private:
TEST(Init, ValidValues) {
BSONObj modObj;
ModifierCompare mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
modObj = fromjson("{ $min : { a : 2 } }");
ASSERT_OK(mod.init(modObj[kModNameMin].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{ $max : { a : 1 } }");
ASSERT_OK(mod.init(modObj[kModNameMax].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{ $min : { a : {$date : 0 } } }");
ASSERT_OK(mod.init(modObj[kModNameMin].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(ExistingNumber, MaxSameNumber) {
@@ -297,7 +301,9 @@ TEST(ExistingEmbeddedDoc, MaxNumber) {
TEST(Collation, MinRespectsCollationFromModifierInterfaceOptions) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
Document doc(fromjson("{a: 'cbc'}"));
- ModifierInterface::Options options = ModifierInterface::Options::normal(&collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
+ ModifierInterface::Options options = ModifierInterface::Options::normal(expCtx);
Mod mod(fromjson("{$min: {a: 'dba'}}"), options);
ModifierInterface::ExecInfo execInfo;
diff --git a/src/mongo/db/ops/modifier_current_date_test.cpp b/src/mongo/db/ops/modifier_current_date_test.cpp
index 79f0e409aa8..cd0f872d018 100644
--- a/src/mongo/db/ops/modifier_current_date_test.cpp
+++ b/src/mongo/db/ops/modifier_current_date_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/logical_clock.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/service_context_noop.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/stdx/memory.h"
@@ -44,6 +45,7 @@
namespace {
using mongo::BSONObj;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierCurrentDate;
using mongo::ModifierInterface;
@@ -101,7 +103,7 @@ public:
explicit Mod(BSONObj modObj) : _modObj(modObj), _mod() {
ASSERT_OK(_mod.init(_modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -128,68 +130,70 @@ private:
TEST_F(Init, ValidValues) {
BSONObj modObj;
ModifierCurrentDate mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
modObj = fromjson("{ $currentDate : { a : true } }");
ASSERT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{ $currentDate : { a : {$type : 'timestamp' } } }");
ASSERT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{ $currentDate : { a : {$type : 'date' } } }");
ASSERT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST_F(Init, FailToInitWithInvalidValue) {
BSONObj modObj;
ModifierCurrentDate mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
// String is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : 'Oct 11, 2001' } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Array is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : [] } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Number is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : 1 } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Regex is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : /1/ } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with missing $type field is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : { foo : 4 } } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with extra fields, including the $type field is bad
modObj = fromjson("{ $currentDate : { a : { $type: 'date', foo : 4 } } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with extra fields, including the $type field is bad
modObj = fromjson("{ $currentDate : { a : { foo: 4, $type : 'date' } } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with non-date/timestamp $type field is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : { $type : 4 } } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// An object with non-date/timestamp $type field is an invalid $currentDate argument
modObj = fromjson("{ $currentDate : { a : { $type : 'foo' } } }");
ASSERT_NOT_OK(mod.init(modObj["$currentDate"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST_F(BoolInput, EmptyStartDoc) {
diff --git a/src/mongo/db/ops/modifier_inc_test.cpp b/src/mongo/db/ops/modifier_inc_test.cpp
index ec12b8deb66..ec0a1b38690 100644
--- a/src/mongo/db/ops/modifier_inc_test.cpp
+++ b/src/mongo/db/ops/modifier_inc_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/platform/decimal128.h"
#include "mongo/unittest/unittest.h"
@@ -46,6 +47,7 @@ namespace {
using mongo::BSONObj;
using mongo::Decimal128;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierInc;
using mongo::ModifierInterface;
@@ -68,7 +70,7 @@ public:
: ModifierInc::MODE_INC) {
StringData modName = modObj.firstElement().fieldName();
ASSERT_OK(_mod.init(_modObj[modName].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -95,21 +97,22 @@ private:
TEST(Init, FailToInitWithInvalidValue) {
BSONObj modObj;
ModifierInc mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
// String is an invalid increment argument
modObj = fromjson("{ $inc : { a : '' } }");
ASSERT_NOT_OK(mod.init(modObj["$inc"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Object is an invalid increment argument
modObj = fromjson("{ $inc : { a : {} } }");
ASSERT_NOT_OK(mod.init(modObj["$inc"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
// Array is an invalid increment argument
modObj = fromjson("{ $inc : { a : [] } }");
ASSERT_NOT_OK(mod.init(modObj["$inc"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, InitParsesNumberInt) {
diff --git a/src/mongo/db/ops/modifier_interface.h b/src/mongo/db/ops/modifier_interface.h
index 77e85a2d447..cb104069ca9 100644
--- a/src/mongo/db/ops/modifier_interface.h
+++ b/src/mongo/db/ops/modifier_interface.h
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/element.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/pipeline/expression_context.h"
namespace mongo {
@@ -168,20 +169,19 @@ public:
* Options used to control Modifier behavior
*/
struct ModifierInterface::Options {
- Options() = default;
- Options(bool fromOpLog, bool ofs, const CollatorInterface* collator)
- : fromOplogApplication(fromOpLog), enforceOkForStorage(ofs), collator(collator) {}
+ Options(bool fromOpLog, bool ofs, boost::intrusive_ptr<ExpressionContext> expCtx)
+ : fromOplogApplication(fromOpLog), enforceOkForStorage(ofs), expCtx(std::move(expCtx)) {}
- static Options normal(const CollatorInterface* collator = nullptr) {
- return Options(false, true, collator);
+ static Options normal(boost::intrusive_ptr<ExpressionContext> expCtx) {
+ return Options(false, true, std::move(expCtx));
}
- static Options fromRepl(const CollatorInterface* collator = nullptr) {
- return Options(true, false, collator);
+ static Options fromRepl(boost::intrusive_ptr<ExpressionContext> expCtx) {
+ return Options(true, false, std::move(expCtx));
}
bool fromOplogApplication = false;
bool enforceOkForStorage = true;
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx;
};
struct ModifierInterface::ExecInfo {
diff --git a/src/mongo/db/ops/modifier_pop_test.cpp b/src/mongo/db/ops/modifier_pop_test.cpp
index 75cb61fac71..f899cedcdd4 100644
--- a/src/mongo/db/ops/modifier_pop_test.cpp
+++ b/src/mongo/db/ops/modifier_pop_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -45,6 +46,7 @@ namespace {
using mongo::Array;
using mongo::BSONObj;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::fromjson;
using mongo::ModifierInterface;
@@ -62,7 +64,7 @@ public:
explicit Mod(BSONObj modObj) {
_modObj = modObj;
ASSERT_OK(_mod.init(_modObj["$pop"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -97,22 +99,25 @@ private:
TEST(Init, StringArg) {
BSONObj modObj = fromjson("{$pop: {a: 'hi'}}");
ModifierPop mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$pop"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, BoolTrueArg) {
BSONObj modObj = fromjson("{$pop: {a: true}}");
ModifierPop mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$pop"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, BoolFalseArg) {
BSONObj modObj = fromjson("{$pop: {a: false}}");
ModifierPop mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$pop"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(MissingField, AllButApply) {
diff --git a/src/mongo/db/ops/modifier_pull.cpp b/src/mongo/db/ops/modifier_pull.cpp
index bb18a80b723..a030e4e5598 100644
--- a/src/mongo/db/ops/modifier_pull.cpp
+++ b/src/mongo/db/ops/modifier_pull.cpp
@@ -99,7 +99,7 @@ Status ModifierPull::init(const BSONElement& modExpr, const Options& opts, bool*
_exprElt = modExpr;
- _collator = opts.collator;
+ _collator = opts.expCtx->getCollator();
// If the element in the mod is actually an object or a regular expression, we need to
// build a matcher, instead of just doing an equality comparision.
@@ -123,7 +123,7 @@ 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/$geoNear/$near/$nearSphere/$expr clauses.
- StatusWithMatchExpression parseResult = MatchExpressionParser::parse(_exprObj, _collator);
+ StatusWithMatchExpression parseResult = MatchExpressionParser::parse(_exprObj, opts.expCtx);
if (!parseResult.isOK()) {
return parseResult.getStatus();
}
diff --git a/src/mongo/db/ops/modifier_pull_all.cpp b/src/mongo/db/ops/modifier_pull_all.cpp
index 0659e91ef38..21455cb66a0 100644
--- a/src/mongo/db/ops/modifier_pull_all.cpp
+++ b/src/mongo/db/ops/modifier_pull_all.cpp
@@ -125,7 +125,7 @@ Status ModifierPullAll::init(const BSONElement& modExpr, const Options& opts, bo
// store the stuff to remove later
_elementsToFind = modExpr.Array();
- setCollator(opts.collator);
+ setCollator(opts.expCtx->getCollator());
return Status::OK();
}
diff --git a/src/mongo/db/ops/modifier_pull_all_test.cpp b/src/mongo/db/ops/modifier_pull_all_test.cpp
index f24c770aa48..8454e5ff616 100644
--- a/src/mongo/db/ops/modifier_pull_all_test.cpp
+++ b/src/mongo/db/ops/modifier_pull_all_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -46,6 +47,7 @@ namespace {
using mongo::BSONObj;
using mongo::CollatorInterfaceMock;
+using mongo::ExpressionContextForTest;
using mongo::LogBuilder;
using mongo::ModifierPullAll;
using mongo::ModifierInterface;
@@ -63,7 +65,8 @@ public:
Mod() : _mod() {}
explicit Mod(BSONObj modObj,
- ModifierInterface::Options options = ModifierInterface::Options::normal())
+ ModifierInterface::Options options =
+ ModifierInterface::Options::normal(new ExpressionContextForTest()))
: _modObj(modObj), _mod() {
ASSERT_OK(_mod.init(_modObj["$pullAll"].embeddedObject().firstElement(), options));
}
@@ -92,22 +95,23 @@ private:
TEST(Init, BadThings) {
BSONObj modObj;
ModifierPullAll mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
modObj = fromjson("{$pullAll: {a:1}}");
ASSERT_NOT_OK(mod.init(modObj["$pullAll"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{$pullAll: {a:'test'}}");
ASSERT_NOT_OK(mod.init(modObj["$pullAll"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{$pullAll: {a:{}}}");
ASSERT_NOT_OK(mod.init(modObj["$pullAll"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
modObj = fromjson("{$pullAll: {a:true}}");
ASSERT_NOT_OK(mod.init(modObj["$pullAll"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(PrepareApply, SimpleNumber) {
@@ -252,8 +256,10 @@ TEST(Prepare, FromArrayElementPath) {
TEST(Collation, RespectsCollationFromOptions) {
Document doc(fromjson("{ a : ['foo', 'bar' ] }"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
Mod mod(fromjson("{ $pullAll : { 'a' : ['FOO', 'BAR'] } }"),
- ModifierInterface::Options::normal(&collator));
+ ModifierInterface::Options::normal(expCtx));
ModifierInterface::ExecInfo execInfo;
ASSERT_OK(mod.prepare(doc.root(), "", &execInfo));
diff --git a/src/mongo/db/ops/modifier_pull_test.cpp b/src/mongo/db/ops/modifier_pull_test.cpp
index 471ed3c18b3..ee5a2025310 100644
--- a/src/mongo/db/ops/modifier_pull_test.cpp
+++ b/src/mongo/db/ops/modifier_pull_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -54,12 +55,14 @@ public:
explicit Mod(BSONObj modObj) : _modObj(modObj), _mod() {
ASSERT_OK(_mod.init(_modObj["$pull"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Mod(BSONObj modObj, const CollatorInterface* collator) : _modObj(modObj), _mod() {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(collator);
ASSERT_OK(_mod.init(_modObj["$pull"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal(collator)));
+ ModifierInterface::Options::normal(std::move(expCtx))));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -85,18 +88,18 @@ private:
TEST(SimpleMod, InitWithTextFails) {
auto update = fromjson("{$pull: {a: {$text: {$search: 'str'}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
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;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -104,9 +107,9 @@ TEST(SimpleMod, InitWithWhereFails) {
TEST(SimpleMod, InitWithGeoNearElemFails) {
auto update =
fromjson("{$pull: {a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -114,27 +117,27 @@ TEST(SimpleMod, InitWithGeoNearElemFails) {
TEST(SimpleMod, InitWithGeoNearObjectFails) {
auto update = fromjson(
"{$pull: {a: {b: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(SimpleMod, InitWithExprElemFails) {
auto update = fromjson("{$pull: {a: {$expr: {$eq: ['$a', 5]}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(SimpleMod, InitWithExprObjectFails) {
auto update = fromjson("{$pull: {a: {$expr: {$eq: ['$a', {$literal: {b: 5}}]}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ModifierPull node;
- auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(collator));
+ auto status = node.init(update["$pull"]["a"], ModifierInterface::Options::normal(expCtx));
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
diff --git a/src/mongo/db/ops/modifier_push.cpp b/src/mongo/db/ops/modifier_push.cpp
index acd6232841a..c062a4e9c34 100644
--- a/src/mongo/db/ops/modifier_push.cpp
+++ b/src/mongo/db/ops/modifier_push.cpp
@@ -338,7 +338,7 @@ Status ModifierPush::init(const BSONElement& modExpr, const Options& opts, bool*
}
}
- _sort = PatternElementCmp(sortElem.embeddedObject(), opts.collator);
+ _sort = PatternElementCmp(sortElem.embeddedObject(), opts.expCtx->getCollator());
} else {
// Ensure the sortElem number is valid.
if (!isPatternElement(sortElem)) {
@@ -346,7 +346,7 @@ Status ModifierPush::init(const BSONElement& modExpr, const Options& opts, bool*
"The $sort element value must be either 1 or -1");
}
- _sort = PatternElementCmp(BSON("" << sortElem.number()), opts.collator);
+ _sort = PatternElementCmp(BSON("" << sortElem.number()), opts.expCtx->getCollator());
}
_sortPresent = true;
diff --git a/src/mongo/db/ops/modifier_push_test.cpp b/src/mongo/db/ops/modifier_push_test.cpp
index cd06eb7d7ff..7c2d65bb485 100644
--- a/src/mongo/db/ops/modifier_push_test.cpp
+++ b/src/mongo/db/ops/modifier_push_test.cpp
@@ -42,6 +42,7 @@
#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -53,6 +54,7 @@ using mongo::BSONObj;
using mongo::BSONObjBuilder;
using mongo::BSONArrayBuilder;
using mongo::CollatorInterfaceMock;
+using mongo::ExpressionContextForTest;
using mongo::fromjson;
using mongo::LogBuilder;
using mongo::ModifierInterface;
@@ -165,8 +167,9 @@ void combineAndSortVec(const vector<BSONObj>& origVec,
TEST(Init, SimplePush) {
BSONObj modObj = fromjson("{$push: {x: 0}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
@@ -176,46 +179,52 @@ TEST(Init, SimplePush) {
TEST(Init, PushEachNormal) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2]}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachMixed) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, {a: 2}]}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachObject) {
// $each must be an array
BSONObj modObj = fromjson("{$push: {x: {$each: {'0': 1}}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachSimpleType) {
// $each must be an array.
BSONObj modObj = fromjson("{$push: {x: {$each: 1}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachEmpty) {
BSONObj modObj = fromjson("{$push: {x: {$each: []}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachInvalidType) {
// $each must be an array.
BSONObj modObj = fromjson("{$push: {x: {$each: {b: 1}}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
@@ -225,50 +234,57 @@ TEST(Init, PushEachInvalidType) {
TEST(Init, PushEachWithSliceBottom) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: -3}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithSliceTop) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: 3}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithInvalidSliceObject) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: {a: 1}}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithInvalidSliceDouble) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: -2.1}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithValidSliceDouble) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: -2.0}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithUnsupportedFullSlice) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: [1,2]}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithWrongTypeSlice) {
BSONObj modObj = fromjson("{$push: {x: {$each: [1, 2], $slice: '-1'}}}");
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
@@ -279,88 +295,99 @@ TEST(Init, PushEachWithObjectSort) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithNumbericSort) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort:1 }}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithInvalidSortType) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: [{a:1}]}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachDuplicateSortPattern) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: [{a:1,a:1}]}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithInvalidSortValue) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {a:100}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithEmptySortField) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {'':1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithEmptyDottedSortField) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {'.':1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithMissingSortFieldSuffix) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {'a.':1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithMissingSortFieldPreffix) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {'.b':1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithMissingSortFieldMiddle) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {'a..b':1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithEmptySort) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort:{} }}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
@@ -371,64 +398,72 @@ TEST(Init, PushEachWithSortMissingSlice) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $sort:{a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachInvalidClause) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $xxx: -1, $sort:{a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachExtraField) {
const char* c = "{$push: {x: {$each: [{a:1},{a:2}], $slice: -2.0, $sort: {a:1}, b: 1}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachDuplicateSortClause) {
const char* c = "{$push: {x:{$each:[{a:1},{a:2}], $slice:-2.0, $sort:{a:1}, $sort:{a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachDuplicateSliceClause) {
const char* c = "{$push: {x: {$each:[{a:1},{a:2}], $slice:-2.0, $slice:-2, $sort:{a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachDuplicateEachClause) {
const char* c = "{$push: {x: {$each:[{a:1}], $each:[{a:2}], $slice:-3, $sort:{a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithSliceFirst) {
const char* c = "{$push: {x: {$slice: -2.0, $each: [{a:1},{a:2}], $sort: {a:1}}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(Init, PushEachWithSortFirst) {
const char* c = "{$push: {x: {$sort: {a:1}, $slice: -2.0, $each: [{a:1},{a:2}]}}}";
BSONObj modObj = fromjson(c);
ModifierPush mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(mod.init(modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
@@ -441,7 +476,8 @@ public:
Mod() : _mod() {}
explicit Mod(BSONObj modObj,
- ModifierInterface::Options options = ModifierInterface::Options::normal())
+ ModifierInterface::Options options =
+ ModifierInterface::Options::normal(new ExpressionContextForTest()))
: _mod() {
_modObj = modObj;
StringData modName = modObj.firstElement().fieldName();
@@ -904,8 +940,10 @@ TEST(SortPushEach, MixedSortEmbeddedField) {
TEST(SortPushEach, SortRespectsCollationFromOptions) {
Document doc(fromjson("{a: ['dd', 'fc', 'gb'] }"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
Mod pushMod(fromjson("{$push: {a: {$each: ['ha'], $sort: 1}}}"),
- ModifierInterface::Options::normal(&collator));
+ ModifierInterface::Options::normal(expCtx));
const BSONObj expectedObj = fromjson("{a: ['ha', 'gb', 'fc', 'dd']}");
ModifierInterface::ExecInfo execInfo;
@@ -967,8 +1005,9 @@ public:
_modObj =
BSON("$push" << BSON("a" << BSON("$each" << arrBuilder.arr() << "$slice" << slice)));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(_mod.init(_modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
/** Sets up the mod to be {$push: {a: {$each:[<Obj>,...], $slice:<slice>, $sort:<Obj>}}} */
@@ -982,8 +1021,9 @@ public:
"$push" << BSON(
"a" << BSON("$each" << arrBuilder.arr() << "$slice" << slice << "$sort" << sort)));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_OK(_mod.init(_modObj["$push"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
/** Returns an object {a: [<'vec's content>]} */
@@ -1190,6 +1230,8 @@ TEST_F(SlicedMod, ObjectArrayFromExisting) {
// Push to position tests
TEST(ToPosition, BadInputs) {
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+
const char* const bad[] = {
"{$push: {a: { $each: [1], $position:'s'}}}",
"{$push: {a: { $each: [1], $position:{}}}}",
@@ -1209,7 +1251,7 @@ TEST(ToPosition, BadInputs) {
ModifierPush pushMod;
BSONObj modObj = fromjson(bad[i]);
ASSERT_NOT_OK(pushMod.init(modObj.firstElement().embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
i++;
}
}
diff --git a/src/mongo/db/ops/modifier_rename_test.cpp b/src/mongo/db/ops/modifier_rename_test.cpp
index fc1c4ee108d..b13337430f2 100644
--- a/src/mongo/db/ops/modifier_rename_test.cpp
+++ b/src/mongo/db/ops/modifier_rename_test.cpp
@@ -37,13 +37,13 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
using mutablebson::ConstElement;
-using mutablebson::Document;
using mutablebson::Element;
/** Helper to build and manipulate the mod. */
@@ -54,7 +54,7 @@ public:
explicit Mod(BSONObj modObj) {
_modObj = modObj;
ASSERT_OK(_mod.init(_modObj["$rename"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -86,55 +86,57 @@ private:
*/
TEST(InvalidInit, FromDbTests) {
ModifierRename mod;
- ASSERT_NOT_OK(
- mod.init(fromjson("{'a.$':'b'}").firstElement(), ModifierInterface::Options::normal()));
- ASSERT_NOT_OK(
- mod.init(fromjson("{'a':'b.$'}").firstElement(), ModifierInterface::Options::normal()));
- ASSERT_NOT_OK(
- mod.init(fromjson("{'.b':'a'}").firstElement(), ModifierInterface::Options::normal()));
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b.':'a'}").firstElement(), ModifierInterface::Options::normal()));
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b':'.a'}").firstElement(), ModifierInterface::Options::normal()));
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b':'a.'}").firstElement(), ModifierInterface::Options::normal()));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(mod.init(fromjson("{'a.$':'b'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
+ ASSERT_NOT_OK(mod.init(fromjson("{'a':'b.$'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
+ ASSERT_NOT_OK(mod.init(fromjson("{'.b':'a'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
+ ASSERT_NOT_OK(mod.init(fromjson("{'b.':'a'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
+ ASSERT_NOT_OK(mod.init(fromjson("{'b':'.a'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
+ ASSERT_NOT_OK(mod.init(fromjson("{'b':'a.'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(InvalidInit, ToFieldCannotContainEmbeddedNullByte) {
ModifierRename mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
{
const auto embeddedNull = "a\0b"_sd;
ASSERT_NOT_OK(mod.init(BSON("a" << embeddedNull).firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
{
const auto singleNullByte = "\0"_sd;
ASSERT_NOT_OK(mod.init(BSON("a" << singleNullByte).firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
{
const auto leadingNullByte = "\0bbbb"_sd;
ASSERT_NOT_OK(mod.init(BSON("a" << leadingNullByte).firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
{
const auto trailingNullByte = "bbbb\0"_sd;
ASSERT_NOT_OK(mod.init(BSON("a" << trailingNullByte).firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
}
TEST(MissingFrom, InitPrepLog) {
- Document doc(fromjson("{a: 2}"));
+ mutablebson::Document doc(fromjson("{a: 2}"));
Mod setMod(fromjson("{$rename: {'b':'a'}}"));
ModifierInterface::ExecInfo execInfo;
ASSERT_OK(setMod.prepare(doc.root(), "", &execInfo));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -142,14 +144,14 @@ TEST(MissingFrom, InitPrepLog) {
}
TEST(MissingFromDotted, InitPrepLog) {
- Document doc(fromjson("{a: {r:2}}"));
+ mutablebson::Document doc(fromjson("{a: {r:2}}"));
Mod setMod(fromjson("{$rename: {'a.b':'a.c'}}"));
ModifierInterface::ExecInfo execInfo;
ASSERT_OK(setMod.prepare(doc.root(), "", &execInfo));
ASSERT_TRUE(execInfo.noOp);
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -157,30 +159,33 @@ TEST(MissingFromDotted, InitPrepLog) {
}
TEST(BasicInit, DifferentRoots) {
- Document doc(fromjson("{a: 2}"));
+ mutablebson::Document doc(fromjson("{a: 2}"));
Mod setMod(fromjson("{$rename: {'a':'f.g'}}"));
}
TEST(MoveOnSamePath, MoveUp) {
ModifierRename mod;
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b.a':'b'}").firstElement(), ModifierInterface::Options::normal()));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(mod.init(fromjson("{'b.a':'b'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(MoveOnSamePath, MoveDown) {
ModifierRename mod;
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b':'b.a'}").firstElement(), ModifierInterface::Options::normal()));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(mod.init(fromjson("{'b':'b.a'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(MoveOnSamePath, MoveToSelf) {
ModifierRename mod;
- ASSERT_NOT_OK(
- mod.init(fromjson("{'b.a':'b.a'}").firstElement(), ModifierInterface::Options::normal()));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_NOT_OK(mod.init(fromjson("{'b.a':'b.a'}").firstElement(),
+ ModifierInterface::Options::normal(expCtx)));
}
TEST(MissingTo, SimpleNumberAtRoot) {
- Document doc(fromjson("{a: 2}"));
+ mutablebson::Document doc(fromjson("{a: 2}"));
Mod setMod(fromjson("{$rename: {'a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -194,7 +199,7 @@ TEST(MissingTo, SimpleNumberAtRoot) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b:2}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b': 2}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -202,7 +207,7 @@ TEST(MissingTo, SimpleNumberAtRoot) {
}
TEST(SimpleReplace, SameLevel) {
- Document doc(fromjson("{a: 2, b: 1}"));
+ mutablebson::Document doc(fromjson("{a: 2, b: 1}"));
Mod setMod(fromjson("{$rename: {'a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -216,7 +221,7 @@ TEST(SimpleReplace, SameLevel) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b:2}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b': 2}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -224,7 +229,7 @@ TEST(SimpleReplace, SameLevel) {
}
TEST(SimpleReplace, FromDottedElement) {
- Document doc(fromjson("{a: {c: {d: 6}}, b: 1}"));
+ mutablebson::Document doc(fromjson("{a: {c: {d: 6}}, b: 1}"));
Mod setMod(fromjson("{$rename: {'a.c':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -238,7 +243,7 @@ TEST(SimpleReplace, FromDottedElement) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{a: {}, b:{ d: 6}}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b': {d: 6}}, $unset: {'a.c': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -246,7 +251,7 @@ TEST(SimpleReplace, FromDottedElement) {
}
TEST(SimpleReplace, RenameToExistingFieldDoesNotReorderFields) {
- Document doc(fromjson("{a: 1, b: 2, c: 3}"));
+ mutablebson::Document doc(fromjson("{a: 1, b: 2, c: 3}"));
Mod setMod(fromjson("{$rename: {a: 'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -259,7 +264,7 @@ TEST(SimpleReplace, RenameToExistingFieldDoesNotReorderFields) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b: 1, c: 3}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set: {b: 1}, $unset: {a: true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -267,7 +272,7 @@ TEST(SimpleReplace, RenameToExistingFieldDoesNotReorderFields) {
}
TEST(SimpleReplace, RenameToExistingNestedFieldDoesNotReorderFields) {
- Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}"));
+ mutablebson::Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}"));
Mod setMod(fromjson("{$rename: {'c.d': 'a.b.c'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -280,7 +285,7 @@ TEST(SimpleReplace, RenameToExistingNestedFieldDoesNotReorderFields) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{a: {b: {c: 4, d: 2}}, b: 3, c: {}}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set: {'a.b.c': 4}, $unset: {'c.d': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -288,7 +293,7 @@ TEST(SimpleReplace, RenameToExistingNestedFieldDoesNotReorderFields) {
}
TEST(DottedTo, MissingCompleteTo) {
- Document doc(fromjson("{a: 2, b: 1, c: {}}"));
+ mutablebson::Document doc(fromjson("{a: 2, b: 1, c: {}}"));
Mod setMod(fromjson("{$rename: {'a':'c.r.d'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -302,7 +307,7 @@ TEST(DottedTo, MissingCompleteTo) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b:1, c: { r: { d: 2}}}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'c.r.d': 2}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -310,7 +315,7 @@ TEST(DottedTo, MissingCompleteTo) {
}
TEST(DottedTo, ToIsCompletelyMissing) {
- Document doc(fromjson("{a: 2}"));
+ mutablebson::Document doc(fromjson("{a: 2}"));
Mod setMod(fromjson("{$rename: {'a':'b.c.d'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -324,7 +329,7 @@ TEST(DottedTo, ToIsCompletelyMissing) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b: {c: {d: 2}}}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b.c.d': 2}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -332,7 +337,7 @@ TEST(DottedTo, ToIsCompletelyMissing) {
}
TEST(FromArrayOfEmbeddedDocs, ToMissingDottedField) {
- Document doc(fromjson("{a: [ {a:2, b:1} ] }"));
+ mutablebson::Document doc(fromjson("{a: [ {a:2, b:1} ] }"));
Mod setMod(fromjson("{$rename: {'a':'b.c.d'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -346,7 +351,7 @@ TEST(FromArrayOfEmbeddedDocs, ToMissingDottedField) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b: {c: {d: [ {a:2, b:1} ]}}}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b.c.d': [ {a:2, b:1} ]}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -354,7 +359,7 @@ TEST(FromArrayOfEmbeddedDocs, ToMissingDottedField) {
}
TEST(FromArrayOfEmbeddedDocs, ToArray) {
- Document doc(fromjson("{a: [ {a:2, b:1} ] }"));
+ mutablebson::Document doc(fromjson("{a: [ {a:2, b:1} ] }"));
Mod setMod(fromjson("{$rename: {'a.a':'a.b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -362,7 +367,7 @@ TEST(FromArrayOfEmbeddedDocs, ToArray) {
}
TEST(Arrays, MoveInto) {
- Document doc(fromjson("{a: [1, 2], b:2}"));
+ mutablebson::Document doc(fromjson("{a: [1, 2], b:2}"));
Mod setMod(fromjson("{$rename: {'b':'a.2'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -370,7 +375,7 @@ TEST(Arrays, MoveInto) {
}
TEST(Arrays, MoveOut) {
- Document doc(fromjson("{a: [1, 2]}"));
+ mutablebson::Document doc(fromjson("{a: [1, 2]}"));
Mod setMod(fromjson("{$rename: {'a.0':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -378,7 +383,7 @@ TEST(Arrays, MoveOut) {
}
TEST(Arrays, MoveNonexistantEmbeddedFieldOut) {
- Document doc(fromjson("{a: [{a:1}, {b:2}]}"));
+ mutablebson::Document doc(fromjson("{a: [{a:1}, {b:2}]}"));
Mod setMod(fromjson("{$rename: {'a.a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -386,7 +391,7 @@ TEST(Arrays, MoveNonexistantEmbeddedFieldOut) {
}
TEST(Arrays, MoveEmbeddedFieldOutWithElementNumber) {
- Document doc(fromjson("{a: [{a:1}, {b:2}]}"));
+ mutablebson::Document doc(fromjson("{a: [{a:1}, {b:2}]}"));
Mod setMod(fromjson("{$rename: {'a.0.a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -394,7 +399,7 @@ TEST(Arrays, MoveEmbeddedFieldOutWithElementNumber) {
}
TEST(Arrays, ReplaceArrayField) {
- Document doc(fromjson("{a: 2, b: []}"));
+ mutablebson::Document doc(fromjson("{a: 2, b: []}"));
Mod setMod(fromjson("{$rename: {'a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -408,7 +413,7 @@ TEST(Arrays, ReplaceArrayField) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b:2}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b': 2}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -417,7 +422,7 @@ TEST(Arrays, ReplaceArrayField) {
TEST(Arrays, ReplaceWithArrayField) {
- Document doc(fromjson("{a: [], b: 2}"));
+ mutablebson::Document doc(fromjson("{a: [], b: 2}"));
Mod setMod(fromjson("{$rename: {'a':'b'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -431,7 +436,7 @@ TEST(Arrays, ReplaceWithArrayField) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{b:[]}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'b': []}, $unset: {'a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
@@ -439,7 +444,7 @@ TEST(Arrays, ReplaceWithArrayField) {
}
TEST(LegacyData, CanRenameFromInvalidFieldName) {
- Document doc(fromjson("{$a: 2}"));
+ mutablebson::Document doc(fromjson("{$a: 2}"));
Mod setMod(fromjson("{$rename: {'$a':'a'}}"));
ModifierInterface::ExecInfo execInfo;
@@ -453,7 +458,7 @@ TEST(LegacyData, CanRenameFromInvalidFieldName) {
ASSERT_FALSE(doc.isInPlaceModeEnabled());
ASSERT_EQUALS(doc, fromjson("{a:2}"));
- Document logDoc;
+ mutablebson::Document logDoc;
LogBuilder logBuilder(logDoc.root());
BSONObj logObj = fromjson("{$set:{ 'a': 2}, $unset: {'$a': true}}");
ASSERT_OK(setMod.log(&logBuilder));
diff --git a/src/mongo/db/ops/modifier_set.cpp b/src/mongo/db/ops/modifier_set.cpp
index fa0e11126c9..60f2fa07608 100644
--- a/src/mongo/db/ops/modifier_set.cpp
+++ b/src/mongo/db/ops/modifier_set.cpp
@@ -60,7 +60,7 @@ struct ModifierSet::PreparedState {
};
ModifierSet::ModifierSet(ModifierSet::ModifierSetMode mode)
- : _fieldRef(), _posDollar(0), _setMode(mode), _val(), _modOptions() {}
+ : _fieldRef(), _posDollar(0), _setMode(mode), _val() {}
ModifierSet::~ModifierSet() {}
@@ -100,7 +100,7 @@ Status ModifierSet::init(const BSONElement& modExpr, const Options& opts, bool*
return Status(ErrorCodes::BadValue, "cannot $set an empty value");
_val = modExpr;
- _modOptions = opts;
+ _fromOplogApplication = opts.fromOplogApplication;
return Status::OK();
}
@@ -133,7 +133,7 @@ Status ModifierSet::prepare(mutablebson::Element root,
// proceed.
if (status.code() == ErrorCodes::NonExistentPath) {
_preparedState->elemFound = root.getDocument().end();
- } else if (_modOptions.fromOplogApplication && status.code() == ErrorCodes::PathNotViable) {
+ } else if (_fromOplogApplication && status.code() == ErrorCodes::PathNotViable) {
// If we are applying an oplog entry and it is an invalid path, then push on indicating that
// we had a blocking element, which we stopped at
_preparedState->elemIsBlocking = true;
@@ -211,7 +211,7 @@ Status ModifierSet::apply() const {
}
// Remove the blocking element, if we are from replication applier. See comment below.
- if (_modOptions.fromOplogApplication && !destExists && _preparedState->elemFound.ok() &&
+ if (_fromOplogApplication && !destExists && _preparedState->elemFound.ok() &&
_preparedState->elemIsBlocking && (!(_preparedState->elemFound.isType(Array)) ||
!(_preparedState->elemFound.isType(Object)))) {
/**
diff --git a/src/mongo/db/ops/modifier_set.h b/src/mongo/db/ops/modifier_set.h
index 4363fa89933..cac403f50a6 100644
--- a/src/mongo/db/ops/modifier_set.h
+++ b/src/mongo/db/ops/modifier_set.h
@@ -97,8 +97,7 @@ private:
// Element of the $set expression.
BSONElement _val;
- // See the class comments in modifier_interface.h
- ModifierInterface::Options _modOptions;
+ bool _fromOplogApplication = false;
// The instance of the field in the provided doc. This state is valid after a
// prepare() was issued and until a log() is issued. The document this mod is
diff --git a/src/mongo/db/ops/modifier_set_test.cpp b/src/mongo/db/ops/modifier_set_test.cpp
index 45c26e495a2..f4ca9c86359 100644
--- a/src/mongo/db/ops/modifier_set_test.cpp
+++ b/src/mongo/db/ops/modifier_set_test.cpp
@@ -38,12 +38,14 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
namespace {
using mongo::BSONObj;
+using mongo::ExpressionContextForTest;
using mongo::fromjson;
using mongo::LogBuilder;
using mongo::ModifierInterface;
@@ -67,9 +69,10 @@ public:
: ModifierSet::SET_NORMAL) {
_modObj = modObj;
StringData modName = modObj.firstElement().fieldName();
- ASSERT_OK(_mod.init(_modObj[modName].embeddedObject().firstElement(),
- !fromRepl ? ModifierInterface::Options::normal()
- : ModifierInterface::Options::fromRepl()));
+ ASSERT_OK(_mod.init(
+ _modObj[modName].embeddedObject().firstElement(),
+ !fromRepl ? ModifierInterface::Options::normal(new ExpressionContextForTest())
+ : ModifierInterface::Options::fromRepl(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
@@ -100,8 +103,9 @@ private:
TEST(Init, EmptyOperation) {
BSONObj modObj = fromjson("{$set: {}}");
ModifierSet mod;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ASSERT_NOT_OK(mod.init(modObj["$set"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(expCtx)));
}
//
diff --git a/src/mongo/db/ops/modifier_unset_test.cpp b/src/mongo/db/ops/modifier_unset_test.cpp
index dfffe5be383..a4f159e3347 100644
--- a/src/mongo/db/ops/modifier_unset_test.cpp
+++ b/src/mongo/db/ops/modifier_unset_test.cpp
@@ -38,6 +38,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/unittest/unittest.h"
@@ -45,6 +46,7 @@ namespace {
using mongo::Array;
using mongo::BSONObj;
+using mongo::ExpressionContextForTest;
using mongo::fromjson;
using mongo::LogBuilder;
using mongo::ModifierInterface;
@@ -62,7 +64,7 @@ public:
explicit Mod(BSONObj modObj) {
_modObj = modObj;
ASSERT_OK(_mod.init(_modObj["$unset"].embeddedObject().firstElement(),
- ModifierInterface::Options::normal()));
+ ModifierInterface::Options::normal(new ExpressionContextForTest())));
}
Status prepare(Element root, StringData matchedField, ModifierInterface::ExecInfo* execInfo) {
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index 576147bdcee..c3da51e352e 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -41,7 +41,10 @@
namespace mongo {
ParsedUpdate::ParsedUpdate(OperationContext* opCtx, const UpdateRequest* request)
- : _opCtx(opCtx), _request(request), _driver(UpdateDriver::Options()), _canonicalQuery() {}
+ : _opCtx(opCtx),
+ _request(request),
+ _driver(UpdateDriver::Options(new ExpressionContext(opCtx, nullptr))),
+ _canonicalQuery() {}
Status ParsedUpdate::parseRequest() {
// It is invalid to request that the UpdateStage return the prior or newly-updated version
@@ -112,11 +115,11 @@ Status ParsedUpdate::parseQueryToCQ() {
qr->setLimit(1);
}
- const boost::intrusive_ptr<ExpressionContext> expCtx;
+ boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(_opCtx,
std::move(qr),
- expCtx,
+ std::move(expCtx),
extensionsCallback,
MatchExpressionParser::kAllowAllSpecialFeatures &
~MatchExpressionParser::AllowedFeatures::kExpr);
@@ -138,8 +141,9 @@ Status ParsedUpdate::parseUpdate() {
!(_request->isFromOplogApplication() || ns.isConfigDB() || _request->isFromMigration());
_driver.setLogOp(true);
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(_opCtx, _collator.get()));
_driver.setModOptions(ModifierInterface::Options(
- _request->isFromOplogApplication(), shouldValidate, _collator.get()));
+ _request->isFromOplogApplication(), shouldValidate, std::move(expCtx)));
return _driver.parse(_request->getUpdates(), _arrayFilters, _request->isMulti());
}
@@ -156,7 +160,10 @@ Status ParsedUpdate::parseArrayFilters() {
}
for (auto rawArrayFilter : _request->getArrayFilters()) {
- auto arrayFilterStatus = ExpressionWithPlaceholder::parse(rawArrayFilter, _collator.get());
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(_opCtx, _collator.get()));
+ auto arrayFilterStatus =
+ ExpressionWithPlaceholder::parse(rawArrayFilter, std::move(expCtx));
if (!arrayFilterStatus.isOK()) {
return Status(arrayFilterStatus.getStatus().code(),
str::stream() << "Error parsing array filter: "
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 9c661c03925..8c5b31ab53a 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -108,8 +108,12 @@ UpdateResult update(OperationContext* opCtx, Database* db, const UpdateRequest&
return UpdateStage::makeUpdateResult(updateStats);
}
-BSONObj applyUpdateOperators(const BSONObj& from, const BSONObj& operators) {
- UpdateDriver::Options opts;
+BSONObj applyUpdateOperators(OperationContext* opCtx,
+ const BSONObj& from,
+ const BSONObj& operators) {
+ const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
+ UpdateDriver::Options opts(std::move(expCtx));
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
Status status = driver.parse(operators, arrayFilters);
diff --git a/src/mongo/db/ops/update.h b/src/mongo/db/ops/update.h
index 5b7f0a4e324..8555401cde9 100644
--- a/src/mongo/db/ops/update.h
+++ b/src/mongo/db/ops/update.h
@@ -56,5 +56,7 @@ UpdateResult update(OperationContext* opCtx, Database* db, const UpdateRequest&
* applyUpdateOperators( BSON( "x" << 1 ) , BSON( "$inc" << BSON( "x" << 1 ) ) );
* returns: { x : 2 }
*/
-BSONObj applyUpdateOperators(const BSONObj& from, const BSONObj& operators);
+BSONObj applyUpdateOperators(OperationContext* opCtx,
+ const BSONObj& from,
+ const BSONObj& operators);
} // namespace mongo
diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript
index 4d249a56456..c15481279a2 100644
--- a/src/mongo/db/pipeline/SConscript
+++ b/src/mongo/db/pipeline/SConscript
@@ -156,9 +156,9 @@ env.CppUnitTest(
'document_source',
'document_source_facet',
'document_source_lookup',
+ 'document_source_mock',
'document_value_test_util',
'$BUILD_DIR/mongo/db/auth/authorization_manager_mock_init',
- '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/db/repl/oplog_entry',
'$BUILD_DIR/mongo/db/repl/replmocks',
'$BUILD_DIR/mongo/db/service_context',
@@ -250,7 +250,6 @@ docSourceEnv.Library(
'document_source_list_sessions.cpp',
'document_source_match.cpp',
'document_source_merge_cursors.cpp',
- 'document_source_mock.cpp',
'document_source_out.cpp',
'document_source_project.cpp',
'document_source_redact.cpp',
@@ -291,6 +290,17 @@ docSourceEnv.Library(
)
env.Library(
+ target='document_source_mock',
+ source=[
+ 'document_source_mock.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
+ 'document_source',
+ ]
+)
+
+env.Library(
target='lite_parsed_document_source',
source=[
'lite_parsed_document_source.cpp',
@@ -353,10 +363,10 @@ env.CppUnitTest(
source='document_source_facet_test.cpp',
LIBDEPS=[
'$BUILD_DIR/mongo/db/auth/authorization_manager_mock_init',
- '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/db/service_context_noop_init',
'$BUILD_DIR/mongo/s/is_mongos',
'document_source_facet',
+ 'document_source_mock',
'document_value_test_util',
],
)
@@ -369,6 +379,7 @@ env.CppUnitTest(
'$BUILD_DIR/mongo/db/service_context_noop_init',
'$BUILD_DIR/mongo/s/is_mongos',
'document_source_facet',
+ 'document_source_mock',
'document_value_test_util',
],
)
@@ -389,6 +400,7 @@ env.CppUnitTest(
source='accumulator_test.cpp',
LIBDEPS=[
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'accumulator',
'document_value_test_util',
],
@@ -403,13 +415,13 @@ env.CppUnitTest(
LIBDEPS=[
'$BUILD_DIR/mongo/db/auth/authorization_manager_mock_init',
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
- '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/db/repl/replmocks',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/db/service_context_noop_init',
'$BUILD_DIR/mongo/s/is_mongos',
'document_value_test_util',
'document_source_lookup',
+ 'document_source_mock',
'pipeline',
],
)
@@ -446,6 +458,7 @@ env.CppUnitTest(
target='parsed_exclusion_projection_test',
source='parsed_exclusion_projection_test.cpp',
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'document_value_test_util',
'parsed_aggregation_projection',
],
@@ -455,6 +468,7 @@ env.CppUnitTest(
target='parsed_aggregation_projection_test',
source='parsed_aggregation_projection_test.cpp',
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'parsed_aggregation_projection',
],
)
@@ -463,6 +477,7 @@ env.CppUnitTest(
target='parsed_inclusion_projection_test',
source='parsed_inclusion_projection_test.cpp',
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'document_value_test_util',
'parsed_aggregation_projection',
],
@@ -475,6 +490,7 @@ env.CppUnitTest(
'granularity_rounder_preferred_numbers_test.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'document_value_test_util',
'granularity_rounder',
],
@@ -484,6 +500,7 @@ env.CppUnitTest(
target='parsed_add_fields_test',
source='parsed_add_fields_test.cpp',
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'document_value_test_util',
'parsed_aggregation_projection',
],
diff --git a/src/mongo/db/pipeline/accumulator_test.cpp b/src/mongo/db/pipeline/accumulator_test.cpp
index 4ed1a6b486b..a50676d1734 100644
--- a/src/mongo/db/pipeline/accumulator_test.cpp
+++ b/src/mongo/db/pipeline/accumulator_test.cpp
@@ -213,8 +213,8 @@ TEST(Accumulators, Min) {
TEST(Accumulators, MinRespectsCollation) {
intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- expCtx->setCollator(
- stdx::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString));
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ expCtx->setCollator(&collator);
assertExpectedResults("$min", expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("cba"_sd)}});
}
@@ -239,8 +239,8 @@ TEST(Accumulators, Max) {
TEST(Accumulators, MaxRespectsCollation) {
intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- expCtx->setCollator(
- stdx::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString));
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ expCtx->setCollator(&collator);
assertExpectedResults("$max", expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("abc"_sd)}});
}
@@ -336,8 +336,8 @@ TEST(Accumulators, Sum) {
TEST(Accumulators, AddToSetRespectsCollation) {
intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- expCtx->setCollator(
- stdx::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kAlwaysEqual));
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ expCtx->setCollator(&collator);
assertExpectedResults("$addToSet",
expCtx,
{{{Value("a"_sd), Value("b"_sd), Value("c"_sd)},
diff --git a/src/mongo/db/pipeline/aggregation_context_fixture.h b/src/mongo/db/pipeline/aggregation_context_fixture.h
index b2b538159f0..b2833c5a70b 100644
--- a/src/mongo/db/pipeline/aggregation_context_fixture.h
+++ b/src/mongo/db/pipeline/aggregation_context_fixture.h
@@ -31,11 +31,7 @@
#include <boost/intrusive_ptr.hpp>
#include <memory>
-#include "mongo/db/client.h"
#include "mongo/db/pipeline/expression_context_for_test.h"
-#include "mongo/db/query/datetime/date_time_support.h"
-#include "mongo/db/query/query_test_service_context.h"
-#include "mongo/db/service_context_noop.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
@@ -49,21 +45,13 @@ public:
AggregationContextFixture()
: AggregationContextFixture(NamespaceString("unittests.pipeline_test")) {}
- AggregationContextFixture(NamespaceString nss)
- : _queryServiceContext(stdx::make_unique<QueryTestServiceContext>()),
- _opCtx(_queryServiceContext->makeOperationContext()),
- _expCtx(new ExpressionContextForTest(_opCtx.get(), AggregationRequest(nss, {}))) {
- TimeZoneDatabase::set(_queryServiceContext->getServiceContext(),
- stdx::make_unique<TimeZoneDatabase>());
- }
+ AggregationContextFixture(NamespaceString nss) : _expCtx(new ExpressionContextForTest(nss)) {}
boost::intrusive_ptr<ExpressionContextForTest> getExpCtx() {
return _expCtx.get();
}
private:
- std::unique_ptr<QueryTestServiceContext> _queryServiceContext;
- ServiceContext::UniqueOperationContext _opCtx;
boost::intrusive_ptr<ExpressionContextForTest> _expCtx;
};
} // namespace mongo
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
index efac859eed0..19f49a2b2a7 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
@@ -545,7 +545,7 @@ intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::createFromBson(
// We don't need to keep ahold of the MatchExpression, but we do need to ensure that
// the specified object is parseable and does not contain extensions.
auto parsedMatchExpression =
- MatchExpressionParser::parse(argument.embeddedObject(), nullptr);
+ MatchExpressionParser::parse(argument.embeddedObject(), expCtx);
uassert(40186,
str::stream()
diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp
index 5a954c63358..c3003eb1d68 100644
--- a/src/mongo/db/pipeline/document_source_match.cpp
+++ b/src/mongo/db/pipeline/document_source_match.cpp
@@ -371,7 +371,6 @@ void DocumentSourceMatch::joinMatchWith(intrusive_ptr<DocumentSourceMatch> other
StatusWithMatchExpression status = uassertStatusOK(
MatchExpressionParser::parse(_predicate,
- pExpCtx->getCollator(),
pExpCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::AllowedFeatures::kText |
@@ -499,12 +498,8 @@ DocumentSourceMatch::DocumentSourceMatch(const BSONObj& query,
_isTextQuery(isTextQuery(query)),
_dependencies(_isTextQuery ? DepsTracker::MetadataAvailable::kTextScore
: DepsTracker::MetadataAvailable::kNoMetadata) {
- StatusWithMatchExpression status =
- uassertStatusOK(MatchExpressionParser::parse(_predicate,
- pExpCtx->getCollator(),
- pExpCtx,
- ExtensionsCallbackNoop(),
- Pipeline::kAllowedMatcherFeatures));
+ StatusWithMatchExpression status = uassertStatusOK(MatchExpressionParser::parse(
+ _predicate, pExpCtx, ExtensionsCallbackNoop(), Pipeline::kAllowedMatcherFeatures));
_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 b327f811cd1..a22eabc993d 100644
--- a/src/mongo/db/pipeline/document_source_match_test.cpp
+++ b/src/mongo/db/pipeline/document_source_match_test.cpp
@@ -521,7 +521,7 @@ DEATH_TEST_F(DocumentSourceMatchTest,
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a.b" << 1 << "b.c" << 1);
const auto matchExpression =
- unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx));
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
}
@@ -531,7 +531,7 @@ DEATH_TEST_F(DocumentSourceMatchTest,
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a" << BSON("$elemMatch" << BSON("a.b" << 1)));
const auto matchExpression =
- unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx));
BSONObjBuilder out;
matchExpression->serialize(&out);
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
@@ -546,7 +546,7 @@ DEATH_TEST_F(DocumentSourceMatchTest,
const auto expCtx = getExpCtx();
const auto matchSpec = BSON("a" << BSON("$elemMatch" << BSON("$gt" << 0)));
const auto matchExpression =
- unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx->getCollator()));
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx));
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
}
@@ -554,7 +554,7 @@ 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, expCtx->getCollator()));
+ unittest::assertGet(MatchExpressionParser::parse(matchSpec, expCtx));
const auto descendedMatch =
DocumentSourceMatch::descendMatchOnPath(matchExpression.get(), "a", expCtx);
diff --git a/src/mongo/db/pipeline/expression_context.cpp b/src/mongo/db/pipeline/expression_context.cpp
index db80c5f7234..37c2f957983 100644
--- a/src/mongo/db/pipeline/expression_context.cpp
+++ b/src/mongo/db/pipeline/expression_context.cpp
@@ -43,35 +43,40 @@ ExpressionContext::ExpressionContext(OperationContext* opCtx,
const AggregationRequest& request,
std::unique_ptr<CollatorInterface> collator,
StringMap<ResolvedNamespace> resolvedNamespaces)
- : explain(request.getExplain()),
- fromMongos(request.isFromMongos()),
- needsMerge(request.needsMerge()),
- allowDiskUse(request.shouldAllowDiskUse()),
- bypassDocumentValidation(request.shouldBypassDocumentValidation()),
- from34Mongos(request.isFrom34Mongos()),
- ns(request.getNamespaceString()),
- opCtx(opCtx),
- collation(request.getCollation()),
+ : ExpressionContext(opCtx, collator.get()) {
+ explain = request.getExplain();
+ fromMongos = request.isFromMongos();
+ needsMerge = request.needsMerge();
+ allowDiskUse = request.shouldAllowDiskUse();
+ bypassDocumentValidation = request.shouldBypassDocumentValidation();
+ from34Mongos = request.isFrom34Mongos();
+ ns = request.getNamespaceString();
+ collation = request.getCollation();
+ _ownedCollator = std::move(collator);
+ _resolvedNamespaces = std::move(resolvedNamespaces);
+}
+ExpressionContext::ExpressionContext(OperationContext* opCtx, const CollatorInterface* collator)
+ : opCtx(opCtx),
variablesParseState(variables.useIdGenerator()),
- _collator(std::move(collator)),
- _documentComparator(_collator.get()),
- _valueComparator(_collator.get()),
- _resolvedNamespaces(std::move(resolvedNamespaces)) {}
+ _collator(collator),
+ _documentComparator(_collator),
+ _valueComparator(_collator) {}
void ExpressionContext::checkForInterrupt() {
// This check could be expensive, at least in relative terms, so don't check every time.
if (--_interruptCounter == 0) {
+ invariant(opCtx);
opCtx->checkForInterrupt();
_interruptCounter = kInterruptCheckPeriod;
}
}
-void ExpressionContext::setCollator(std::unique_ptr<CollatorInterface> coll) {
- _collator = std::move(coll);
+void ExpressionContext::setCollator(const CollatorInterface* collator) {
+ _collator = collator;
// Document/Value comparisons must be aware of the collation.
- _documentComparator = DocumentComparator(_collator.get());
- _valueComparator = ValueComparator(_collator.get());
+ _documentComparator = DocumentComparator(_collator);
+ _valueComparator = ValueComparator(_collator);
}
intrusive_ptr<ExpressionContext> ExpressionContext::copyWith(NamespaceString ns,
@@ -92,8 +97,10 @@ intrusive_ptr<ExpressionContext> ExpressionContext::copyWith(NamespaceString ns,
expCtx->opCtx = opCtx;
expCtx->collation = collation;
- if (_collator) {
- expCtx->setCollator(_collator->clone());
+ if (_ownedCollator) {
+ expCtx->setCollator(_ownedCollator->clone());
+ } else if (_collator) {
+ expCtx->setCollator(_collator);
}
expCtx->_resolvedNamespaces = _resolvedNamespaces;
diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h
index d580644eeba..0e7488aaa55 100644
--- a/src/mongo/db/pipeline/expression_context.h
+++ b/src/mongo/db/pipeline/expression_context.h
@@ -70,15 +70,23 @@ public:
StringMap<ExpressionContext::ResolvedNamespace> resolvedNamespaces);
/**
+ * Constructs an ExpressionContext to be used for MatchExpression parsing outside of the context
+ * of aggregation.
+ */
+ ExpressionContext(OperationContext* opCtx, const CollatorInterface* collator);
+
+ /**
* Used by a pipeline to check for interrupts so that killOp() works. Throws a UserAssertion if
* this aggregation pipeline has been interrupted.
*/
void checkForInterrupt();
const CollatorInterface* getCollator() const {
- return _collator.get();
+ return _collator;
}
+ void setCollator(const CollatorInterface* collator);
+
const DocumentComparator& getDocumentComparator() const {
return _documentComparator;
}
@@ -148,15 +156,23 @@ protected:
: ns(std::move(nss)), variablesParseState(variables.useIdGenerator()) {}
/**
- * Sets '_collator' and resets '_documentComparator' and '_valueComparator'.
+ * Sets '_ownedCollator' and resets '_collator', 'documentComparator' and 'valueComparator'.
*
- * Use with caution - it is illegal to change the collation once a Pipeline has been parsed with
- * this ExpressionContext.
+ * Use with caution - '_ownedCollator' is used in the context of a Pipeline, and it is illegal
+ * to change the collation once a Pipeline has been parsed with this ExpressionContext.
*/
- void setCollator(std::unique_ptr<CollatorInterface> collator);
+ void setCollator(std::unique_ptr<CollatorInterface> collator) {
+ _ownedCollator = std::move(collator);
+ setCollator(_ownedCollator.get());
+ }
+
+ // Collator used for comparisons. This is owned in the context of a Pipeline.
+ // TODO SERVER-31294: Move ownership of an aggregation's collator elsewhere.
+ std::unique_ptr<CollatorInterface> _ownedCollator;
- // Collator used for comparisons.
- std::unique_ptr<CollatorInterface> _collator;
+ // Collator used for comparisons. If '_ownedCollator' is non-null, then this must point to the
+ // same collator object.
+ const CollatorInterface* _collator = nullptr;
// Used for all comparisons of Document/Value during execution of the aggregation operation.
// Must not be changed after parsing a Pipeline with this ExpressionContext.
diff --git a/src/mongo/db/pipeline/expression_context_for_test.h b/src/mongo/db/pipeline/expression_context_for_test.h
index 542e5b91eea..b54bb82094f 100644
--- a/src/mongo/db/pipeline/expression_context_for_test.h
+++ b/src/mongo/db/pipeline/expression_context_for_test.h
@@ -29,38 +29,42 @@
#pragma once
#include "mongo/db/pipeline/expression_context.h"
+#include "mongo/db/query/datetime/date_time_support.h"
+#include "mongo/db/query/query_test_service_context.h"
namespace mongo {
/**
- * An ExpressionContext that can have state like the collation and resolved namespace map
- * manipulated after construction. In contrast, a regular ExpressionContext requires the collation
- * and resolved namespaces to be provided on construction and does not allow them to be subsequently
+ * An ExpressionContext with a default OperationContext that can have state (like the resolved
+ * namespace map) manipulated after construction. In contrast, a regular ExpressionContext requires
+ * the resolved namespaces to be provided on construction and does not allow them to be subsequently
* mutated.
*/
class ExpressionContextForTest : public ExpressionContext {
public:
- ExpressionContextForTest() : ExpressionContext(NamespaceString{"test"_sd, "namespace"_sd}) {}
+ ExpressionContextForTest()
+ : ExpressionContextForTest(NamespaceString{"test"_sd, "namespace"_sd}) {}
- ExpressionContextForTest(NamespaceString nss) : ExpressionContext(std::move(nss)) {}
+ ExpressionContextForTest(NamespaceString nss)
+ : ExpressionContext(std::move(nss)), _testOpCtx(_serviceContext.makeOperationContext()) {
+ TimeZoneDatabase::set(_serviceContext.getServiceContext(),
+ stdx::make_unique<TimeZoneDatabase>());
+ opCtx = _testOpCtx.get();
+ }
ExpressionContextForTest(OperationContext* opCtx, const AggregationRequest& request)
: ExpressionContext(opCtx, request, nullptr, {}) {}
/**
- * Changes the collation used by this ExpressionContext. Must not be changed after parsing a
- * Pipeline with this ExpressionContext.
- */
- void setCollator(std::unique_ptr<CollatorInterface> collator) {
- ExpressionContext::setCollator(std::move(collator));
- }
-
- /**
* Sets the resolved definition for an involved namespace.
*/
void setResolvedNamespace(const NamespaceString& nss, ResolvedNamespace resolvedNamespace) {
_resolvedNamespaces[nss.coll()] = std::move(resolvedNamespace);
}
+
+private:
+ QueryTestServiceContext _serviceContext;
+ ServiceContext::UniqueOperationContext _testOpCtx;
};
} // namespace mongo
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index f3b5fd2546c..6a0d30887b6 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -73,7 +73,6 @@ env.Library(
"internal_plans",
"query_common",
"query_planner",
- "query_planner_test_lib",
'$BUILD_DIR/mongo/db/catalog/collection',
'$BUILD_DIR/mongo/db/catalog/database',
'$BUILD_DIR/mongo/db/catalog/index_catalog',
@@ -279,7 +278,6 @@ env.Library(
],
LIBDEPS=[
"query_planner_test_lib",
- "query_test_service_context",
"$BUILD_DIR/mongo/unittest/unittest",
],
)
@@ -292,6 +290,7 @@ env.Library(
LIBDEPS=[
"collation/collator_factory_mock",
"query_planner",
+ "query_test_service_context",
],
)
@@ -325,6 +324,7 @@ env.CppUnitTest(
LIBDEPS=[
"collation/collator_interface_mock",
"index_bounds",
+ "query_test_service_context",
],
)
@@ -366,6 +366,7 @@ env.CppUnitTest(
],
LIBDEPS=[
"query_planner",
+ "query_test_service_context",
],
)
@@ -388,6 +389,7 @@ env.CppUnitTest(
LIBDEPS=[
"collation/collator_interface_mock",
"query_planner",
+ "query_test_service_context",
],
)
@@ -409,6 +411,7 @@ env.CppUnitTest(
LIBDEPS=[
"collation/collator_interface_mock",
"query_planner",
+ "query_test_service_context",
],
)
@@ -435,6 +438,7 @@ env.CppUnitTest(
LIBDEPS=[
"collation/collator_factory_mock",
"query_planner",
+ "query_test_service_context",
],
)
diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp
index 1df80364b65..515ba518658 100644
--- a/src/mongo/db/query/canonical_query.cpp
+++ b/src/mongo/db/query/canonical_query.cpp
@@ -147,8 +147,14 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
}
// Make MatchExpression.
+ boost::intrusive_ptr<ExpressionContext> newExpCtx;
+ if (!expCtx.get()) {
+ newExpCtx.reset(new ExpressionContext(opCtx, collator.get()));
+ } else {
+ newExpCtx = expCtx;
+ }
StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
- qr->getFilter(), collator.get(), expCtx, extensionsCallback, allowedFeatures);
+ qr->getFilter(), newExpCtx, extensionsCallback, allowedFeatures);
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
@@ -158,7 +164,8 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery());
Status initStatus =
- cq->init(std::move(qr),
+ cq->init(opCtx,
+ std::move(qr),
parsingCanProduceNoopMatchNodes(extensionsCallback, allowedFeatures),
me.release(),
std::move(collator));
@@ -192,7 +199,8 @@ 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),
+ Status initStatus = cq->init(opCtx,
+ std::move(qr),
baseQuery.canHaveNoopMatchNodes(),
root->shallowClone().release(),
std::move(collator));
@@ -203,7 +211,8 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
return std::move(cq);
}
-Status CanonicalQuery::init(std::unique_ptr<QueryRequest> qr,
+Status CanonicalQuery::init(OperationContext* opCtx,
+ std::unique_ptr<QueryRequest> qr,
bool canHaveNoopMatchNodes,
MatchExpression* root,
std::unique_ptr<CollatorInterface> collator) {
@@ -226,7 +235,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);
+ Status projStatus = ParsedProjection::make(opCtx, _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 392c75ca704..eb3d077c6ca 100644
--- a/src/mongo/db/query/canonical_query.h
+++ b/src/mongo/db/query/canonical_query.h
@@ -190,7 +190,8 @@ private:
// You must go through canonicalize to create a CanonicalQuery.
CanonicalQuery() {}
- Status init(std::unique_ptr<QueryRequest> qr,
+ Status init(OperationContext* opCtx,
+ std::unique_ptr<QueryRequest> qr,
bool canHaveNoopMatchNodes,
MatchExpression* root,
std::unique_ptr<CollatorInterface> collator);
diff --git a/src/mongo/db/query/canonical_query_test.cpp b/src/mongo/db/query/canonical_query_test.cpp
index 04048242c64..1ab63a0c16f 100644
--- a/src/mongo/db/query/canonical_query_test.cpp
+++ b/src/mongo/db/query/canonical_query_test.cpp
@@ -54,12 +54,10 @@ static const NamespaceString nss("testdb.testcoll");
* and return the MatchExpression*.
*/
MatchExpression* parseMatchExpression(const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
- const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression status =
MatchExpressionParser::parse(obj,
- collator,
- expCtx,
+ std::move(expCtx),
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
if (!status.isOK()) {
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 0560aa907f3..cf241557d19 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -662,7 +662,7 @@ StatusWith<unique_ptr<PlanStage>> applyProjection(OperationContext* opCtx,
invariant(!proj.isEmpty());
ParsedProjection* rawParsedProj;
- Status ppStatus = ParsedProjection::make(proj.getOwned(), cq->root(), &rawParsedProj);
+ Status ppStatus = ParsedProjection::make(opCtx, proj.getOwned(), cq->root(), &rawParsedProj);
if (!ppStatus.isOK()) {
return ppStatus;
}
diff --git a/src/mongo/db/query/index_bounds_builder_test.cpp b/src/mongo/db/query/index_bounds_builder_test.cpp
index ec85f567ae1..f7d0e23794e 100644
--- a/src/mongo/db/query/index_bounds_builder_test.cpp
+++ b/src/mongo/db/query/index_bounds_builder_test.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/expression_index.h"
#include "mongo/unittest/unittest.h"
@@ -58,8 +59,8 @@ double NaN = numeric_limits<double>::quiet_NaN();
* Utility function to create MatchExpression
*/
MatchExpression* parseMatchExpression(const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
ASSERT_TRUE(status.isOK());
MatchExpression* expr(status.getValue().release());
return expr;
diff --git a/src/mongo/db/query/parsed_projection.cpp b/src/mongo/db/query/parsed_projection.cpp
index 575c5d5dff5..069ff5a235e 100644
--- a/src/mongo/db/query/parsed_projection.cpp
+++ b/src/mongo/db/query/parsed_projection.cpp
@@ -46,7 +46,8 @@ using std::string;
* Returns a Status indicating how it's invalid otherwise.
*/
// static
-Status ParsedProjection::make(const BSONObj& spec,
+Status ParsedProjection::make(OperationContext* opCtx,
+ const BSONObj& spec,
const MatchExpression* const query,
ParsedProjection** out) {
// Whether we're including or excluding fields.
@@ -129,8 +130,10 @@ Status ParsedProjection::make(const BSONObj& spec,
// Match expression extensions such as $text, $where, $geoNear, $near, $nearSphere,
// and $expr are not allowed in $elemMatch projections.
const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(elemMatchObj, collator);
+ MatchExpressionParser::parse(elemMatchObj, std::move(expCtx));
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 2f273c5d303..82544e82c47 100644
--- a/src/mongo/db/query/parsed_projection.h
+++ b/src/mongo/db/query/parsed_projection.h
@@ -45,7 +45,8 @@ public:
* Returns Status::OK() if it's a valid spec.
* Returns a Status indicating how it's invalid otherwise.
*/
- static Status make(const BSONObj& spec,
+ static Status make(OperationContext* opCtx,
+ const BSONObj& spec,
const MatchExpression* const query,
ParsedProjection** out);
diff --git a/src/mongo/db/query/parsed_projection_test.cpp b/src/mongo/db/query/parsed_projection_test.cpp
index 22046f8b531..e184cef3d6a 100644
--- a/src/mongo/db/query/parsed_projection_test.cpp
+++ b/src/mongo/db/query/parsed_projection_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_always_boolean.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/query/query_test_service_context.h"
#include "mongo/unittest/unittest.h"
#include <memory>
@@ -47,12 +48,17 @@ using namespace mongo;
//
unique_ptr<ParsedProjection> createParsedProjection(const BSONObj& query, const BSONObj& projObj) {
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(query, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx.get(), collator));
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(query, std::move(expCtx));
ASSERT(statusWithMatcher.isOK());
std::unique_ptr<MatchExpression> queryMatchExpr = std::move(statusWithMatcher.getValue());
ParsedProjection* out = NULL;
- Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
+ Status status = ParsedProjection::make(opCtx.get(), projObj, queryMatchExpr.get(), &out);
if (!status.isOK()) {
FAIL(mongoutils::str::stream() << "failed to parse projection " << projObj << " (query: "
<< query
@@ -76,12 +82,17 @@ unique_ptr<ParsedProjection> createParsedProjection(const char* queryStr, const
void assertInvalidProjection(const char* queryStr, const char* projStr) {
BSONObj query = fromjson(queryStr);
BSONObj projObj = fromjson(projStr);
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(query, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx.get(), collator));
+ StatusWithMatchExpression statusWithMatcher =
+ MatchExpressionParser::parse(query, std::move(expCtx));
ASSERT(statusWithMatcher.isOK());
std::unique_ptr<MatchExpression> queryMatchExpr = std::move(statusWithMatcher.getValue());
ParsedProjection* out = NULL;
- Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
+ Status status = ParsedProjection::make(opCtx.get(), projObj, queryMatchExpr.get(), &out);
std::unique_ptr<ParsedProjection> destroy(out);
ASSERT(!status.isOK());
}
@@ -199,18 +210,20 @@ TEST(ParsedProjectionTest, ValidPositionalOperatorProjections) {
// to achieve the same effect.
// Projection parser should handle this the same way as an empty path.
TEST(ParsedProjectionTest, InvalidPositionalProjectionDefaultPathMatchExpression) {
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
unique_ptr<MatchExpression> queryMatchExpr(new AlwaysFalseMatchExpression());
ASSERT(NULL == queryMatchExpr->path().rawData());
ParsedProjection* out = NULL;
BSONObj projObj = fromjson("{'a.$': 1}");
- Status status = ParsedProjection::make(projObj, queryMatchExpr.get(), &out);
+ Status status = ParsedProjection::make(opCtx.get(), 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);
+ status = ParsedProjection::make(opCtx.get(), 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 11635c4b665..5d008f9665a 100644
--- a/src/mongo/db/query/plan_cache_indexability_test.cpp
+++ b/src/mongo/db/query/plan_cache_indexability_test.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.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"
@@ -40,7 +41,9 @@ namespace {
std::unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj,
const CollatorInterface* collator = nullptr) {
- StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
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 b94ab624fe1..eb588910785 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -73,7 +73,7 @@ unique_ptr<CanonicalQuery> canonicalize(const BSONObj& queryObj) {
auto qr = stdx::make_unique<QueryRequest>(nss);
qr->setFilter(queryObj);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -101,7 +101,7 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setSort(fromjson(sortStr));
qr->setProj(fromjson(projStr));
qr->setCollation(fromjson(collationStr));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -136,7 +136,7 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setHint(fromjson(hintStr));
qr->setMin(fromjson(minStr));
qr->setMax(fromjson(maxStr));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -175,7 +175,7 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setMax(fromjson(maxStr));
qr->setSnapshot(snapshot);
qr->setExplain(explain);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -190,12 +190,10 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
* Utility function to create MatchExpression
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression status =
MatchExpressionParser::parse(obj,
- collator,
- expCtx,
+ std::move(expCtx),
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
if (!status.isOK()) {
@@ -589,7 +587,7 @@ protected:
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -616,7 +614,7 @@ protected:
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -702,7 +700,7 @@ protected:
qr->setSort(sort);
qr->setProj(proj);
qr->setCollation(collation);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
diff --git a/src/mongo/db/query/planner_ixselect_test.cpp b/src/mongo/db/query/planner_ixselect_test.cpp
index 6d90afdb275..50053c7659b 100644
--- a/src/mongo/db/query/planner_ixselect_test.cpp
+++ b/src/mongo/db/query/planner_ixselect_test.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/index_tag.h"
#include "mongo/unittest/unittest.h"
@@ -54,8 +55,8 @@ using std::vector;
* Utility function to create MatchExpression
*/
unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression status = MatchExpressionParser::parse(obj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
ASSERT_TRUE(status.isOK());
return std::move(status.getValue());
}
diff --git a/src/mongo/db/query/query_planner_test_fixture.cpp b/src/mongo/db/query/query_planner_test_fixture.cpp
index ae04eec22a4..5ba4eb2648e 100644
--- a/src/mongo/db/query/query_planner_test_fixture.cpp
+++ b/src/mongo/db/query/query_planner_test_fixture.cpp
@@ -249,7 +249,7 @@ void QueryPlannerTest::runQueryFull(const BSONObj& query,
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -333,7 +333,7 @@ void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
qr->setMin(minObj);
qr->setMax(maxObj);
qr->setSnapshot(snapshot);
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -359,7 +359,7 @@ void QueryPlannerTest::runQueryAsCommand(const BSONObj& cmdObj) {
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -385,7 +385,7 @@ void QueryPlannerTest::runInvalidQueryAsCommand(const BSONObj& cmdObj) {
std::unique_ptr<QueryRequest> qr(
assertGet(QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain)));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
std::move(qr),
@@ -472,7 +472,9 @@ 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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(collator);
+ StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
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 c1920f821d0..377bbb791ae 100644
--- a/src/mongo/db/query/query_planner_test_lib.cpp
+++ b/src/mongo/db/query/query_planner_test_lib.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_factory_mock.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_solution.h"
@@ -66,8 +67,10 @@ bool filterMatches(const BSONObj& testFilter,
testCollator = std::move(collator.getValue());
}
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(testCollator.get());
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(testFilter, testCollator.get());
+ MatchExpressionParser::parse(testFilter, std::move(expCtx));
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 821b1efd4e9..0e07d9669a6 100644
--- a/src/mongo/db/query/query_solution_test.cpp
+++ b/src/mongo/db/query/query_solution_test.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/query/index_bounds_builder.h"
#include "mongo/db/query/index_entry.h"
#include "mongo/db/query/query_solution.h"
+#include "mongo/db/query/query_test_service_context.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
@@ -685,11 +686,17 @@ TEST(QuerySolutionTest, IndexScanNodeHasFieldExcludesSimpleBoundsStringFieldWhen
std::unique_ptr<ParsedProjection> createParsedProjection(const BSONObj& query,
const BSONObj& projObj) {
+ QueryTestServiceContext serviceCtx;
+ auto opCtx = serviceCtx.makeOperationContext();
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression queryMatchExpr = MatchExpressionParser::parse(query, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtx.get(), collator));
+ StatusWithMatchExpression queryMatchExpr =
+ MatchExpressionParser::parse(query, std::move(expCtx));
ASSERT(queryMatchExpr.isOK());
ParsedProjection* out = nullptr;
- Status status = ParsedProjection::make(projObj, queryMatchExpr.getValue().get(), &out);
+ Status status =
+ ParsedProjection::make(opCtx.get(), 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/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp
index af561045a00..cf634cb4712 100644
--- a/src/mongo/db/repl/apply_ops.cpp
+++ b/src/mongo/db/repl/apply_ops.cpp
@@ -309,7 +309,8 @@ Status _checkPrecondition(OperationContext* opCtx,
// applyOps does not allow any extensions, such as $text, $where, $geoNear, $near,
// $nearSphere, or $expr.
- Matcher matcher(preCondition["res"].Obj(), collator);
+ boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
+ Matcher matcher(preCondition["res"].Obj(), std::move(expCtx));
if (!matcher.matches(realres)) {
result->append("got", realres);
result->append("whatFailed", preCondition);
diff --git a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp
index ee8a60a9fa3..98f3808f9ef 100644
--- a/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp
+++ b/src/mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.cpp
@@ -386,7 +386,7 @@ void NamespaceDetailsCollectionCatalogEntry::_updateSystemNamespaces(OperationCo
return;
RecordData entry = _namespacesRecordStore->dataFor(opCtx, _namespacesRecordId);
- const BSONObj newEntry = applyUpdateOperators(entry.releaseToBson(), update);
+ const BSONObj newEntry = applyUpdateOperators(opCtx, entry.releaseToBson(), update);
Status result = _namespacesRecordStore->updateRecord(
opCtx, _namespacesRecordId, newEntry.objdata(), newEntry.objsize(), false, NULL);
diff --git a/src/mongo/db/update/SConscript b/src/mongo/db/update/SConscript
index 2bbb89d7db5..082ae597b66 100644
--- a/src/mongo/db/update/SConscript
+++ b/src/mongo/db/update/SConscript
@@ -49,6 +49,7 @@ env.CppUnitTest(
LIBDEPS=[
'$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
'$BUILD_DIR/mongo/db/matcher/expressions',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'update_common',
],
)
@@ -118,6 +119,7 @@ env.CppUnitTest(
'$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils',
'$BUILD_DIR/mongo/db/logical_clock',
'$BUILD_DIR/mongo/db/query/collation/collator_interface_mock',
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/db/service_context_noop_init',
'update',
],
diff --git a/src/mongo/db/update/addtoset_node.cpp b/src/mongo/db/update/addtoset_node.cpp
index f0a43dca382..89eb53f8bd6 100644
--- a/src/mongo/db/update/addtoset_node.cpp
+++ b/src/mongo/db/update/addtoset_node.cpp
@@ -61,7 +61,8 @@ void deduplicate(std::vector<BSONElement>& elements, const CollatorInterface* co
} // namespace
-Status AddToSetNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status AddToSetNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
bool isEach = false;
@@ -92,7 +93,7 @@ Status AddToSetNode::init(BSONElement modExpr, const CollatorInterface* collator
_elements.push_back(modExpr);
}
- setCollator(collator);
+ setCollator(expCtx->getCollator());
return Status::OK();
}
diff --git a/src/mongo/db/update/addtoset_node.h b/src/mongo/db/update/addtoset_node.h
index b5677caf169..25fcddffcb5 100644
--- a/src/mongo/db/update/addtoset_node.h
+++ b/src/mongo/db/update/addtoset_node.h
@@ -38,7 +38,7 @@ namespace mongo {
*/
class AddToSetNode : public ModifierNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<AddToSetNode>(*this);
diff --git a/src/mongo/db/update/addtoset_node_test.cpp b/src/mongo/db/update/addtoset_node_test.cpp
index 26e6e1ea4fc..7fe1e95ca45 100644
--- a/src/mongo/db/update/addtoset_node_test.cpp
+++ b/src/mongo/db/update/addtoset_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
@@ -47,16 +48,16 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(AddToSetNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$addToSet: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- node.init(update["$addToSet"].embeddedObject().firstElement(), collator).transitional_ignore();
+ node.init(update["$addToSet"].embeddedObject().firstElement(), expCtx).transitional_ignore();
}
TEST(AddToSetNodeTest, InitFailsIfEachIsNotArray) {
auto update = fromjson("{$addToSet: {a: {$each: {}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- auto result = node.init(update["$addToSet"]["a"], collator);
+ auto result = node.init(update["$addToSet"]["a"], expCtx);
ASSERT_NOT_OK(result);
ASSERT_EQ(result.code(), ErrorCodes::TypeMismatch);
ASSERT_EQ(result.reason(),
@@ -65,9 +66,9 @@ TEST(AddToSetNodeTest, InitFailsIfEachIsNotArray) {
TEST(AddToSetNodeTest, InitFailsIfThereAreFieldsAfterEach) {
auto update = fromjson("{$addToSet: {a: {$each: [], bad: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- auto result = node.init(update["$addToSet"]["a"], collator);
+ auto result = node.init(update["$addToSet"]["a"], expCtx);
ASSERT_NOT_OK(result);
ASSERT_EQ(result.code(), ErrorCodes::BadValue);
ASSERT_EQ(result.reason(),
@@ -76,37 +77,37 @@ TEST(AddToSetNodeTest, InitFailsIfThereAreFieldsAfterEach) {
TEST(AddToSetNodeTest, InitSucceedsWithFailsBeforeEach) {
auto update = fromjson("{$addToSet: {a: {other: 1, $each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
}
TEST(AddToSetNodeTest, InitSucceedsWithObject) {
auto update = fromjson("{$addToSet: {a: {}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
}
TEST(AddToSetNodeTest, InitSucceedsWithArray) {
auto update = fromjson("{$addToSet: {a: []}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
}
TEST(AddToSetNodeTest, InitSucceedsWithScaler) {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
}
TEST_F(AddToSetNodeTest, ApplyFailsOnNonArray) {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2}"));
setPathTaken("a");
@@ -119,9 +120,9 @@ TEST_F(AddToSetNodeTest, ApplyFailsOnNonArray) {
TEST_F(AddToSetNodeTest, ApplyNonEach) {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -136,9 +137,9 @@ TEST_F(AddToSetNodeTest, ApplyNonEach) {
TEST_F(AddToSetNodeTest, ApplyNonEachArray) {
auto update = fromjson("{$addToSet: {a: [1]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -153,9 +154,9 @@ TEST_F(AddToSetNodeTest, ApplyNonEachArray) {
TEST_F(AddToSetNodeTest, ApplyEach) {
auto update = fromjson("{$addToSet: {a: {$each: [1, 2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -170,9 +171,9 @@ TEST_F(AddToSetNodeTest, ApplyEach) {
TEST_F(AddToSetNodeTest, ApplyToEmptyArray) {
auto update = fromjson("{$addToSet: {a: {$each: [1, 2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -187,9 +188,9 @@ TEST_F(AddToSetNodeTest, ApplyToEmptyArray) {
TEST_F(AddToSetNodeTest, ApplyDeduplicateElementsToAdd) {
auto update = fromjson("{$addToSet: {a: {$each: [1, 1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -204,9 +205,9 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicateElementsToAdd) {
TEST_F(AddToSetNodeTest, ApplyDoNotAddExistingElements) {
auto update = fromjson("{$addToSet: {a: {$each: [0, 1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -221,9 +222,9 @@ TEST_F(AddToSetNodeTest, ApplyDoNotAddExistingElements) {
TEST_F(AddToSetNodeTest, ApplyDoNotDeduplicateExistingElements) {
auto update = fromjson("{$addToSet: {a: {$each: [1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 0]}"));
setPathTaken("a");
@@ -238,9 +239,9 @@ TEST_F(AddToSetNodeTest, ApplyDoNotDeduplicateExistingElements) {
TEST_F(AddToSetNodeTest, ApplyNoElementsToAdd) {
auto update = fromjson("{$addToSet: {a: {$each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -255,9 +256,9 @@ TEST_F(AddToSetNodeTest, ApplyNoElementsToAdd) {
TEST_F(AddToSetNodeTest, ApplyNoNonDuplicateElementsToAdd) {
auto update = fromjson("{$addToSet: {a: {$each: [0]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -272,9 +273,9 @@ TEST_F(AddToSetNodeTest, ApplyNoNonDuplicateElementsToAdd) {
TEST_F(AddToSetNodeTest, ApplyCreateArray) {
auto update = fromjson("{$addToSet: {a: {$each: [0, 1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -289,9 +290,9 @@ TEST_F(AddToSetNodeTest, ApplyCreateArray) {
TEST_F(AddToSetNodeTest, ApplyCreateEmptyArrayIsNotNoop) {
auto update = fromjson("{$addToSet: {a: {$each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -306,9 +307,11 @@ TEST_F(AddToSetNodeTest, ApplyCreateEmptyArrayIsNotNoop) {
TEST_F(AddToSetNodeTest, ApplyDeduplicationOfElementsToAddRespectsCollation) {
auto update = fromjson("{$addToSet: {a: {$each: ['abc', 'ABC', 'def', 'abc']}}}");
- const CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], &collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -323,9 +326,11 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicationOfElementsToAddRespectsCollation) {
TEST_F(AddToSetNodeTest, ApplyComparisonToExistingElementsRespectsCollation) {
auto update = fromjson("{$addToSet: {a: {$each: ['abc', 'def']}}}");
- const CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], &collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['ABC']}"));
setPathTaken("a");
@@ -340,9 +345,9 @@ TEST_F(AddToSetNodeTest, ApplyComparisonToExistingElementsRespectsCollation) {
TEST_F(AddToSetNodeTest, ApplyRespectsCollationFromSetCollator) {
auto update = fromjson("{$addToSet: {a: {$each: ['abc', 'ABC', 'def', 'abc']}}}");
- const CollatorInterface* binaryComparisonCollator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], binaryComparisonCollator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
const CollatorInterfaceMock caseInsensitiveCollator(
CollatorInterfaceMock::MockType::kToLowerString);
@@ -361,18 +366,19 @@ TEST_F(AddToSetNodeTest, ApplyRespectsCollationFromSetCollator) {
DEATH_TEST(AddToSetNodeTest, CannotSetCollatorIfCollatorIsNonNull, "Invariant failure !_collator") {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterfaceMock caseInsensitiveCollator(
- CollatorInterfaceMock::MockType::kToLowerString);
+ CollatorInterfaceMock caseInsensitiveCollator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&caseInsensitiveCollator);
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], &caseInsensitiveCollator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
node.setCollator(&caseInsensitiveCollator);
}
DEATH_TEST(AddToSetNodeTest, CannotSetCollatorTwice, "Invariant failure !_collator") {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* binaryComparisonCollator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], binaryComparisonCollator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
const CollatorInterfaceMock caseInsensitiveCollator(
CollatorInterfaceMock::MockType::kToLowerString);
@@ -382,9 +388,9 @@ DEATH_TEST(AddToSetNodeTest, CannotSetCollatorTwice, "Invariant failure !_collat
TEST_F(AddToSetNodeTest, ApplyNestedArray) {
auto update = fromjson("{ $addToSet : { 'a.1' : 1 } }");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a.1"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a.1"], expCtx));
mutablebson::Document doc(fromjson("{ _id : 1, a : [ 1, [ ] ] }"));
setPathTaken("a.1");
@@ -399,9 +405,9 @@ TEST_F(AddToSetNodeTest, ApplyNestedArray) {
TEST_F(AddToSetNodeTest, ApplyIndexesNotAffected) {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -415,9 +421,9 @@ TEST_F(AddToSetNodeTest, ApplyIndexesNotAffected) {
TEST_F(AddToSetNodeTest, ApplyNoIndexDataOrLogBuilder) {
auto update = fromjson("{$addToSet: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
AddToSetNode node;
- ASSERT_OK(node.init(update["$addToSet"]["a"], collator));
+ ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
diff --git a/src/mongo/db/update/arithmetic_node.cpp b/src/mongo/db/update/arithmetic_node.cpp
index c5b7a3373f7..ab46e854616 100644
--- a/src/mongo/db/update/arithmetic_node.cpp
+++ b/src/mongo/db/update/arithmetic_node.cpp
@@ -58,7 +58,8 @@ const char* getModifierNameForOp(ArithmeticNode::ArithmeticOp op) {
}
} // namespace
-Status ArithmeticNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status ArithmeticNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
if (!modExpr.isNumber()) {
diff --git a/src/mongo/db/update/arithmetic_node.h b/src/mongo/db/update/arithmetic_node.h
index 14981e0778e..cc5e9b23dc8 100644
--- a/src/mongo/db/update/arithmetic_node.h
+++ b/src/mongo/db/update/arithmetic_node.h
@@ -42,7 +42,7 @@ public:
explicit ArithmeticNode(ArithmeticOp op) : _op(op) {}
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<ArithmeticNode>(*this);
diff --git a/src/mongo/db/update/arithmetic_node_test.cpp b/src/mongo/db/update/arithmetic_node_test.cpp
index 64f1ad3c8d3..f8cd87927c6 100644
--- a/src/mongo/db/update/arithmetic_node_test.cpp
+++ b/src/mongo/db/update/arithmetic_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -46,44 +47,44 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(ArithmeticNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$inc: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- node.init(update["$inc"].embeddedObject().firstElement(), collator).transitional_ignore();
+ node.init(update["$inc"].embeddedObject().firstElement(), expCtx).transitional_ignore();
}
TEST(ArithmeticNodeTest, InitSucceedsForNumberIntElement) {
auto update = fromjson("{$inc: {a: NumberInt(5)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
}
TEST(ArithmeticNodeTest, InitSucceedsForNumberLongElement) {
auto update = fromjson("{$inc: {a: NumberLong(5)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
}
TEST(ArithmeticNodeTest, InitSucceedsForDoubleElement) {
auto update = fromjson("{$inc: {a: 5.1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
}
TEST(ArithmeticNodeTest, InitSucceedsForDecimalElement) {
auto update = fromjson("{$inc: {a: NumberDecimal(\"5.1\")}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
}
TEST(ArithmeticNodeTest, InitFailsForNonNumericElement) {
auto update = fromjson("{$inc: {a: 'foo'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- Status result = node.init(update["$inc"]["a"], collator);
+ Status result = node.init(update["$inc"]["a"], expCtx);
ASSERT_NOT_OK(result);
ASSERT_EQ(result.code(), ErrorCodes::TypeMismatch);
ASSERT_EQ(result.reason(), "Cannot increment with non-numeric argument: {a: \"foo\"}");
@@ -91,9 +92,9 @@ TEST(ArithmeticNodeTest, InitFailsForNonNumericElement) {
TEST(ArithmeticNodeTest, InitFailsForObjectElement) {
auto update = fromjson("{$mul: {a: {b: 6}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- Status result = node.init(update["$mul"]["a"], collator);
+ Status result = node.init(update["$mul"]["a"], expCtx);
ASSERT_NOT_OK(result);
ASSERT_EQ(result.code(), ErrorCodes::TypeMismatch);
ASSERT_EQ(result.reason(), "Cannot multiply with non-numeric argument: {a: { b: 6 }}");
@@ -101,9 +102,9 @@ TEST(ArithmeticNodeTest, InitFailsForObjectElement) {
TEST(ArithmeticNodeTest, InitFailsForArrayElement) {
auto update = fromjson("{$mul: {a: []}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- Status result = node.init(update["$mul"]["a"], collator);
+ Status result = node.init(update["$mul"]["a"], expCtx);
ASSERT_NOT_OK(result);
ASSERT_EQ(result.code(), ErrorCodes::TypeMismatch);
ASSERT_EQ(result.reason(), "Cannot multiply with non-numeric argument: {a: []}");
@@ -111,9 +112,9 @@ TEST(ArithmeticNodeTest, InitFailsForArrayElement) {
TEST_F(ArithmeticNodeTest, ApplyIncNoOp) {
auto update = fromjson("{$inc: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -128,9 +129,9 @@ TEST_F(ArithmeticNodeTest, ApplyIncNoOp) {
TEST_F(ArithmeticNodeTest, ApplyMulNoOp) {
auto update = fromjson("{$mul: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -145,9 +146,9 @@ TEST_F(ArithmeticNodeTest, ApplyMulNoOp) {
TEST_F(ArithmeticNodeTest, ApplyRoundingNoOp) {
auto update = fromjson("{$inc: {a: 1.0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 6.022e23}"));
setPathTaken("a");
@@ -162,9 +163,9 @@ TEST_F(ArithmeticNodeTest, ApplyRoundingNoOp) {
TEST_F(ArithmeticNodeTest, ApplyEmptyPathToCreate) {
auto update = fromjson("{$inc: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -179,9 +180,9 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyPathToCreate) {
TEST_F(ArithmeticNodeTest, ApplyCreatePath) {
auto update = fromjson("{$inc: {'a.b.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {d: 5}}"));
setPathToCreate("b.c");
@@ -197,9 +198,9 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePath) {
TEST_F(ArithmeticNodeTest, ApplyExtendPath) {
auto update = fromjson("{$inc: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {c: 1}}"));
setPathToCreate("b");
@@ -214,9 +215,9 @@ TEST_F(ArithmeticNodeTest, ApplyExtendPath) {
TEST_F(ArithmeticNodeTest, ApplyCreatePathFromRoot) {
auto update = fromjson("{$inc: {'a.b': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{c: 5}"));
setPathToCreate("a.b");
@@ -231,9 +232,9 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePathFromRoot) {
TEST_F(ArithmeticNodeTest, ApplyPositional) {
auto update = fromjson("{$inc: {'a.$': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.$"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.$"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2]}"));
setPathTaken("a.1");
@@ -249,9 +250,9 @@ TEST_F(ArithmeticNodeTest, ApplyPositional) {
TEST_F(ArithmeticNodeTest, ApplyNonViablePathToInc) {
auto update = fromjson("{$inc: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathToCreate("b");
@@ -265,9 +266,9 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathToInc) {
TEST_F(ArithmeticNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) {
auto update = fromjson("{$inc: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathToCreate("b");
@@ -284,9 +285,9 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) {
TEST_F(ArithmeticNodeTest, ApplyNoIndexDataNoLogBuilder) {
auto update = fromjson("{$inc: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -300,9 +301,9 @@ TEST_F(ArithmeticNodeTest, ApplyNoIndexDataNoLogBuilder) {
TEST_F(ArithmeticNodeTest, ApplyDoesNotAffectIndexes) {
auto update = fromjson("{$inc: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -316,9 +317,9 @@ TEST_F(ArithmeticNodeTest, ApplyDoesNotAffectIndexes) {
TEST_F(ArithmeticNodeTest, IncTypePromotionIsNotANoOp) {
auto update = fromjson("{$inc: {a: NumberLong(0)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberInt(2)}"));
setPathTaken("a");
@@ -332,9 +333,9 @@ TEST_F(ArithmeticNodeTest, IncTypePromotionIsNotANoOp) {
TEST_F(ArithmeticNodeTest, MulTypePromotionIsNotANoOp) {
auto update = fromjson("{$mul: {a: NumberLong(1)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberInt(2)}"));
setPathTaken("a");
@@ -348,9 +349,9 @@ TEST_F(ArithmeticNodeTest, MulTypePromotionIsNotANoOp) {
TEST_F(ArithmeticNodeTest, TypePromotionFromIntToDecimalIsNotANoOp) {
auto update = fromjson("{$inc: {a: NumberDecimal(\"0.0\")}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberInt(5)}"));
setPathTaken("a");
@@ -365,9 +366,9 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromIntToDecimalIsNotANoOp) {
TEST_F(ArithmeticNodeTest, TypePromotionFromLongToDecimalIsNotANoOp) {
auto update = fromjson("{$inc: {a: NumberDecimal(\"0.0\")}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberLong(5)}"));
setPathTaken("a");
@@ -382,9 +383,9 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromLongToDecimalIsNotANoOp) {
TEST_F(ArithmeticNodeTest, TypePromotionFromDoubleToDecimalIsNotANoOp) {
auto update = fromjson("{$inc: {a: NumberDecimal(\"0.0\")}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5.25}"));
setPathTaken("a");
@@ -399,9 +400,9 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromDoubleToDecimalIsNotANoOp) {
TEST_F(ArithmeticNodeTest, ApplyPromoteToFloatingPoint) {
auto update = fromjson("{$inc: {a: 0.2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberLong(1)}"));
setPathTaken("a");
@@ -415,9 +416,9 @@ TEST_F(ArithmeticNodeTest, ApplyPromoteToFloatingPoint) {
TEST_F(ArithmeticNodeTest, IncrementedDecimalStaysDecimal) {
auto update = fromjson("{$inc: {a: 5.25}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberDecimal(\"6.25\")}"));
setPathTaken("a");
@@ -432,9 +433,9 @@ TEST_F(ArithmeticNodeTest, IncrementedDecimalStaysDecimal) {
TEST_F(ArithmeticNodeTest, OverflowIntToLong) {
auto update = fromjson("{$inc: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
const int initialValue = std::numeric_limits<int>::max();
mutablebson::Document doc(BSON("a" << initialValue));
@@ -451,9 +452,9 @@ TEST_F(ArithmeticNodeTest, OverflowIntToLong) {
TEST_F(ArithmeticNodeTest, UnderflowIntToLong) {
auto update = fromjson("{$inc: {a: -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
const int initialValue = std::numeric_limits<int>::min();
mutablebson::Document doc(BSON("a" << initialValue));
@@ -470,9 +471,9 @@ TEST_F(ArithmeticNodeTest, UnderflowIntToLong) {
TEST_F(ArithmeticNodeTest, IncModeCanBeReused) {
auto update = fromjson("{$inc: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc1(fromjson("{a: 1}"));
mutablebson::Document doc2(fromjson("{a: 2}"));
@@ -496,9 +497,9 @@ TEST_F(ArithmeticNodeTest, IncModeCanBeReused) {
TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsInc) {
auto update = fromjson("{$inc: {a: NumberLong(5)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 6}"));
setPathToCreate("a");
@@ -512,9 +513,9 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsInc) {
TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsMul) {
auto update = fromjson("{$mul: {a: NumberLong(5)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 6}"));
setPathToCreate("a");
@@ -528,9 +529,9 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsMul) {
TEST_F(ArithmeticNodeTest, ApplyEmptyDocument) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -544,9 +545,9 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyDocument) {
TEST_F(ArithmeticNodeTest, ApplyIncToObjectFails) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: {b: 1}}"));
setPathTaken("a");
@@ -560,9 +561,9 @@ TEST_F(ArithmeticNodeTest, ApplyIncToObjectFails) {
TEST_F(ArithmeticNodeTest, ApplyIncToArrayFails) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: []}"));
setPathTaken("a");
@@ -576,9 +577,9 @@ TEST_F(ArithmeticNodeTest, ApplyIncToArrayFails) {
TEST_F(ArithmeticNodeTest, ApplyIncToStringFails) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: \"foo\"}"));
setPathTaken("a");
@@ -592,9 +593,9 @@ TEST_F(ArithmeticNodeTest, ApplyIncToStringFails) {
TEST_F(ArithmeticNodeTest, OverflowingOperationFails) {
auto update = fromjson("{$mul: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: NumberLong(9223372036854775807)}"));
setPathTaken("a");
@@ -609,9 +610,9 @@ TEST_F(ArithmeticNodeTest, OverflowingOperationFails) {
TEST_F(ArithmeticNodeTest, ApplyNewPath) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 1}"));
setPathToCreate("a");
@@ -625,9 +626,9 @@ TEST_F(ArithmeticNodeTest, ApplyNewPath) {
TEST_F(ArithmeticNodeTest, ApplyEmptyIndexData) {
auto update = fromjson("{$inc: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -640,9 +641,9 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyIndexData) {
TEST_F(ArithmeticNodeTest, ApplyNoOpDottedPath) {
auto update = fromjson("{$inc: {'a.b': 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a.b");
@@ -656,9 +657,9 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpDottedPath) {
TEST_F(ArithmeticNodeTest, TypePromotionOnDottedPathIsNotANoOp) {
auto update = fromjson("{$inc: {'a.b': NumberLong(0)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: NumberInt(2)}}"));
setPathTaken("a.b");
@@ -672,9 +673,9 @@ TEST_F(ArithmeticNodeTest, TypePromotionOnDottedPathIsNotANoOp) {
TEST_F(ArithmeticNodeTest, ApplyPathNotViableArray) {
auto update = fromjson("{$inc: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a:[{b:1}]}"));
setPathToCreate("b");
@@ -687,9 +688,9 @@ TEST_F(ArithmeticNodeTest, ApplyPathNotViableArray) {
TEST_F(ArithmeticNodeTest, ApplyInPlaceDottedPath) {
auto update = fromjson("{$inc: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathTaken("a.b");
@@ -703,9 +704,9 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceDottedPath) {
TEST_F(ArithmeticNodeTest, ApplyPromotionDottedPath) {
auto update = fromjson("{$inc: {'a.b': NumberLong(2)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: NumberInt(3)}}"));
setPathTaken("a.b");
@@ -719,9 +720,9 @@ TEST_F(ArithmeticNodeTest, ApplyPromotionDottedPath) {
TEST_F(ArithmeticNodeTest, ApplyDottedPathEmptyDoc) {
auto update = fromjson("{$inc: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a.b");
@@ -735,9 +736,9 @@ TEST_F(ArithmeticNodeTest, ApplyDottedPathEmptyDoc) {
TEST_F(ArithmeticNodeTest, ApplyFieldWithDot) {
auto update = fromjson("{$inc: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{'a.b':4}"));
setPathToCreate("a.b");
@@ -751,9 +752,9 @@ TEST_F(ArithmeticNodeTest, ApplyFieldWithDot) {
TEST_F(ArithmeticNodeTest, ApplyNoOpArrayIndex) {
auto update = fromjson("{$inc: {'a.2.b': 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"));
setPathTaken("a.2.b");
@@ -767,9 +768,9 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpArrayIndex) {
TEST_F(ArithmeticNodeTest, TypePromotionInArrayIsNotANoOp) {
auto update = fromjson("{$set: {'a.2.b': NumberLong(0)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(
fromjson("{a: [{b: NumberInt(0)},{b: NumberInt(1)},{b: NumberInt(2)}]}"));
@@ -784,9 +785,9 @@ TEST_F(ArithmeticNodeTest, TypePromotionInArrayIsNotANoOp) {
TEST_F(ArithmeticNodeTest, ApplyNonViablePathThroughArray) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathToCreate("2.b");
@@ -799,9 +800,9 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathThroughArray) {
TEST_F(ArithmeticNodeTest, ApplyInPlaceArrayIndex) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}"));
setPathTaken("a.2.b");
@@ -815,9 +816,9 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceArrayIndex) {
TEST_F(ArithmeticNodeTest, ApplyAppendArray) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1}]}"));
setPathToCreate("2.b");
@@ -832,9 +833,9 @@ TEST_F(ArithmeticNodeTest, ApplyAppendArray) {
TEST_F(ArithmeticNodeTest, ApplyPaddingArray) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
setPathToCreate("2.b");
@@ -849,9 +850,9 @@ TEST_F(ArithmeticNodeTest, ApplyPaddingArray) {
TEST_F(ArithmeticNodeTest, ApplyNumericObject) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 0}}"));
setPathToCreate("2.b");
@@ -866,9 +867,9 @@ TEST_F(ArithmeticNodeTest, ApplyNumericObject) {
TEST_F(ArithmeticNodeTest, ApplyNumericField) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {'2': {b: 1}}}"));
setPathTaken("a.2.b");
@@ -882,9 +883,9 @@ TEST_F(ArithmeticNodeTest, ApplyNumericField) {
TEST_F(ArithmeticNodeTest, ApplyExtendNumericField) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {'2': {c: 1}}}"));
setPathToCreate("b");
@@ -899,9 +900,9 @@ TEST_F(ArithmeticNodeTest, ApplyExtendNumericField) {
TEST_F(ArithmeticNodeTest, ApplyNumericFieldToEmptyObject) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {}}"));
setPathToCreate("2.b");
@@ -916,9 +917,9 @@ TEST_F(ArithmeticNodeTest, ApplyNumericFieldToEmptyObject) {
TEST_F(ArithmeticNodeTest, ApplyEmptyArray) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathToCreate("2.b");
@@ -933,9 +934,9 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyArray) {
TEST_F(ArithmeticNodeTest, ApplyLogDottedPath) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b:0}, {b:1}]}"));
setPathToCreate("2.b");
@@ -949,9 +950,9 @@ TEST_F(ArithmeticNodeTest, ApplyLogDottedPath) {
TEST_F(ArithmeticNodeTest, LogEmptyArray) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathToCreate("2.b");
@@ -965,9 +966,9 @@ TEST_F(ArithmeticNodeTest, LogEmptyArray) {
TEST_F(ArithmeticNodeTest, LogEmptyObject) {
auto update = fromjson("{$inc: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd);
- ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$inc"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {}}"));
setPathToCreate("2.b");
@@ -981,9 +982,9 @@ TEST_F(ArithmeticNodeTest, LogEmptyObject) {
TEST_F(ArithmeticNodeTest, ApplyDeserializedDocNotNoOp) {
auto update = fromjson("{$mul: {b: NumberInt(1)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["b"], collator));
+ ASSERT_OK(node.init(update["$mul"]["b"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
// De-serialize the int.
@@ -1000,9 +1001,9 @@ TEST_F(ArithmeticNodeTest, ApplyDeserializedDocNotNoOp) {
TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNoOp) {
auto update = fromjson("{$mul: {a: NumberInt(1)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
// De-serialize the int.
@@ -1019,9 +1020,9 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNoOp) {
TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNoop) {
auto update = fromjson("{$mul: {'a.b': NumberInt(1)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a.b"], expCtx));
mutablebson::Document doc{BSONObj()};
// De-serialize the int.
@@ -1038,9 +1039,9 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNoop) {
TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNotNoop) {
auto update = fromjson("{$mul: {'a.b': 3}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply);
- ASSERT_OK(node.init(update["$mul"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$mul"]["a.b"], expCtx));
mutablebson::Document doc{BSONObj()};
// De-serialize the int.
diff --git a/src/mongo/db/update/bit_node.cpp b/src/mongo/db/update/bit_node.cpp
index f2123d6324e..c2ca50dae32 100644
--- a/src/mongo/db/update/bit_node.cpp
+++ b/src/mongo/db/update/bit_node.cpp
@@ -34,7 +34,7 @@
namespace mongo {
-Status BitNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status BitNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
if (modExpr.type() != mongo::Object) {
diff --git a/src/mongo/db/update/bit_node.h b/src/mongo/db/update/bit_node.h
index 2f23d9a53df..f5cecf9220b 100644
--- a/src/mongo/db/update/bit_node.h
+++ b/src/mongo/db/update/bit_node.h
@@ -38,7 +38,7 @@ namespace mongo {
*/
class BitNode : public ModifierNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<BitNode>(*this);
diff --git a/src/mongo/db/update/bit_node_test.cpp b/src/mongo/db/update/bit_node_test.cpp
index 868d064f66b..b6c94542e09 100644
--- a/src/mongo/db/update/bit_node_test.cpp
+++ b/src/mongo/db/update/bit_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -45,115 +46,115 @@ using mongo::mutablebson::Element;
using mongo::mutablebson::countChildren;
TEST(BitNodeTest, InitWithDoubleFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: 0}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithStringFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: ''}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithArrayFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: []}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithEmptyDocumentFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {}}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithUnknownOperatorFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {foo: 4}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithArrayArgumentToOperatorFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {or: []}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithStringArgumentToOperatorFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {or: 'foo'}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithDoubleArgumentToOperatorFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {or: 1.0}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, InitWithDecimalArgumentToOperatorFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$bit: {a: {or: NumberDecimal(\"1.0\")}}}");
BitNode node;
- ASSERT_NOT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesAndInt) {
auto update = fromjson("{$bit: {a: {and: NumberInt(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesOrInt) {
auto update = fromjson("{$bit: {a: {or: NumberInt(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesXorInt) {
auto update = fromjson("{$bit: {a: {xor: NumberInt(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesAndLong) {
auto update = fromjson("{$bit: {a: {and: NumberLong(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesOrLong) {
auto update = fromjson("{$bit: {a: {or: NumberLong(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST(BitNodeTest, ParsesXorLong) {
auto update = fromjson("{$bit: {a: {xor: NumberLong(1)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
}
TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentAnd) {
auto update = fromjson("{$bit: {a: {and: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -166,9 +167,9 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentAnd) {
TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentOr) {
auto update = fromjson("{$bit: {a: {or: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -181,9 +182,9 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentOr) {
TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentXor) {
auto update = fromjson("{$bit: {a: {xor: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -196,9 +197,9 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentXor) {
TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentAnd) {
auto update = BSON("$bit" << BSON("a" << BSON("and" << 0b0110)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 0b0101));
setPathTaken("a");
@@ -211,9 +212,9 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentAnd) {
TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentOr) {
auto update = BSON("$bit" << BSON("a" << BSON("or" << 0b0110)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 0b0101));
setPathTaken("a");
@@ -226,9 +227,9 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentOr) {
TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentXor) {
auto update = BSON("$bit" << BSON("a" << BSON("xor" << 0b0110)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 0b0101));
setPathTaken("a");
@@ -241,9 +242,9 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentXor) {
TEST_F(BitNodeTest, ApplyShouldReportNoOp) {
auto update = BSON("$bit" << BSON("a" << BSON("and" << static_cast<int>(1))));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 1));
setPathTaken("a");
@@ -261,9 +262,9 @@ TEST_F(BitNodeTest, ApplyMultipleBitOps) {
"or" << 0b1100110011001100 //
<< //
"xor" << 0b1010101010101010)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 0b1111111100000000));
setPathTaken("a");
@@ -276,9 +277,9 @@ TEST_F(BitNodeTest, ApplyMultipleBitOps) {
TEST_F(BitNodeTest, ApplyRepeatedBitOps) {
auto update = BSON("$bit" << BSON("a" << BSON("xor" << 0b11001100 << "xor" << 0b10101010)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
BitNode node;
- ASSERT_OK(node.init(update["$bit"]["a"], collator));
+ ASSERT_OK(node.init(update["$bit"]["a"], expCtx));
mutablebson::Document doc(BSON("a" << 0b11110000));
setPathTaken("a");
diff --git a/src/mongo/db/update/compare_node.cpp b/src/mongo/db/update/compare_node.cpp
index 744a452002b..fd4e1202a94 100644
--- a/src/mongo/db/update/compare_node.cpp
+++ b/src/mongo/db/update/compare_node.cpp
@@ -34,10 +34,11 @@
namespace mongo {
-Status CompareNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status CompareNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
_val = modExpr;
- setCollator(collator);
+ setCollator(expCtx->getCollator());
return Status::OK();
}
diff --git a/src/mongo/db/update/compare_node.h b/src/mongo/db/update/compare_node.h
index 6fe9cbd3084..580d0542201 100644
--- a/src/mongo/db/update/compare_node.h
+++ b/src/mongo/db/update/compare_node.h
@@ -42,7 +42,7 @@ public:
explicit CompareNode(CompareMode mode) : _mode(mode) {}
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<CompareNode>(*this);
diff --git a/src/mongo/db/update/compare_node_test.cpp b/src/mongo/db/update/compare_node_test.cpp
index 37949aef2dc..16aa4258222 100644
--- a/src/mongo/db/update/compare_node_test.cpp
+++ b/src/mongo/db/update/compare_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
@@ -47,16 +48,16 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(CompareNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$max: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- node.init(update["$max"].embeddedObject().firstElement(), collator).ignore();
+ node.init(update["$max"].embeddedObject().firstElement(), expCtx).ignore();
}
TEST_F(CompareNodeTest, ApplyMaxSameNumber) {
auto update = fromjson("{$max: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -71,9 +72,9 @@ TEST_F(CompareNodeTest, ApplyMaxSameNumber) {
TEST_F(CompareNodeTest, ApplyMinSameNumber) {
auto update = fromjson("{$min: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -88,9 +89,9 @@ TEST_F(CompareNodeTest, ApplyMinSameNumber) {
TEST_F(CompareNodeTest, ApplyMaxNumberIsLess) {
auto update = fromjson("{$max: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -105,9 +106,9 @@ TEST_F(CompareNodeTest, ApplyMaxNumberIsLess) {
TEST_F(CompareNodeTest, ApplyMinNumberIsMore) {
auto update = fromjson("{$min: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -122,9 +123,9 @@ TEST_F(CompareNodeTest, ApplyMinNumberIsMore) {
TEST_F(CompareNodeTest, ApplyMaxSameValInt) {
auto update = BSON("$max" << BSON("a" << 1LL));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1.0}"));
setPathTaken("a");
@@ -139,9 +140,9 @@ TEST_F(CompareNodeTest, ApplyMaxSameValInt) {
TEST_F(CompareNodeTest, ApplyMaxSameValIntZero) {
auto update = BSON("$max" << BSON("a" << 0LL));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0.0}"));
setPathTaken("a");
@@ -156,9 +157,9 @@ TEST_F(CompareNodeTest, ApplyMaxSameValIntZero) {
TEST_F(CompareNodeTest, ApplyMinSameValIntZero) {
auto update = BSON("$min" << BSON("a" << 0LL));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0.0}"));
setPathTaken("a");
@@ -173,9 +174,9 @@ TEST_F(CompareNodeTest, ApplyMinSameValIntZero) {
TEST_F(CompareNodeTest, ApplyMissingFieldMinNumber) {
auto update = fromjson("{$min: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -190,9 +191,9 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMinNumber) {
TEST_F(CompareNodeTest, ApplyExistingNumberMinNumber) {
auto update = fromjson("{$min: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -207,9 +208,9 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMinNumber) {
TEST_F(CompareNodeTest, ApplyMissingFieldMaxNumber) {
auto update = fromjson("{$max: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -224,9 +225,9 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMaxNumber) {
TEST_F(CompareNodeTest, ApplyExistingNumberMaxNumber) {
auto update = fromjson("{$max: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -241,9 +242,9 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMaxNumber) {
TEST_F(CompareNodeTest, ApplyExistingDateMaxDate) {
auto update = fromjson("{$max: {a: {$date: 123123123}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {$date: 0}}"));
setPathTaken("a");
@@ -258,9 +259,9 @@ TEST_F(CompareNodeTest, ApplyExistingDateMaxDate) {
TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxDoc) {
auto update = fromjson("{$max: {a: {b: 3}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -275,9 +276,9 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxDoc) {
TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxNumber) {
auto update = fromjson("{$max: {a: 3}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -292,9 +293,11 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxNumber) {
TEST_F(CompareNodeTest, ApplyMinRespectsCollation) {
auto update = fromjson("{$min: {a: 'dba'}}");
- const CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], &collator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 'cbc'}"));
setPathTaken("a");
@@ -309,9 +312,9 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollation) {
TEST_F(CompareNodeTest, ApplyMinRespectsCollationFromSetCollator) {
auto update = fromjson("{$min: {a: 'dba'}}");
- const CollatorInterface* binaryComparisonCollator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMin);
- ASSERT_OK(node.init(update["$min"]["a"], binaryComparisonCollator));
+ ASSERT_OK(node.init(update["$min"]["a"], expCtx));
const CollatorInterfaceMock reverseStringCollator(
CollatorInterfaceMock::MockType::kReverseString);
@@ -330,9 +333,9 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollationFromSetCollator) {
TEST_F(CompareNodeTest, ApplyMaxRespectsCollationFromSetCollator) {
auto update = fromjson("{$max: {a: 'abd'}}");
- const CollatorInterface* binaryComparisonCollator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], binaryComparisonCollator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
const CollatorInterfaceMock reverseStringCollator(
CollatorInterfaceMock::MockType::kReverseString);
@@ -351,18 +354,19 @@ TEST_F(CompareNodeTest, ApplyMaxRespectsCollationFromSetCollator) {
DEATH_TEST(CompareNodeTest, CannotSetCollatorIfCollatorIsNonNull, "Invariant failure !_collator") {
auto update = fromjson("{$max: {a: 1}}");
- const CollatorInterfaceMock caseInsensitiveCollator(
- CollatorInterfaceMock::MockType::kToLowerString);
+ CollatorInterfaceMock caseInsensitiveCollator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&caseInsensitiveCollator);
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], &caseInsensitiveCollator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
node.setCollator(&caseInsensitiveCollator);
}
DEATH_TEST(CompareNodeTest, CannotSetCollatorTwice, "Invariant failure !_collator") {
auto update = fromjson("{$max: {a: 1}}");
- const CollatorInterface* binaryComparisonCollator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], binaryComparisonCollator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
const CollatorInterfaceMock caseInsensitiveCollator(
CollatorInterfaceMock::MockType::kToLowerString);
@@ -372,9 +376,9 @@ DEATH_TEST(CompareNodeTest, CannotSetCollatorTwice, "Invariant failure !_collato
TEST_F(CompareNodeTest, ApplyIndexesNotAffected) {
auto update = fromjson("{$max: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -389,9 +393,9 @@ TEST_F(CompareNodeTest, ApplyIndexesNotAffected) {
TEST_F(CompareNodeTest, ApplyNoIndexDataOrLogBuilder) {
auto update = fromjson("{$max: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CompareNode node(CompareNode::CompareMode::kMax);
- ASSERT_OK(node.init(update["$max"]["a"], collator));
+ ASSERT_OK(node.init(update["$max"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
diff --git a/src/mongo/db/update/conflict_placeholder_node.h b/src/mongo/db/update/conflict_placeholder_node.h
index ceb88d69e20..66be569ff7c 100644
--- a/src/mongo/db/update/conflict_placeholder_node.h
+++ b/src/mongo/db/update/conflict_placeholder_node.h
@@ -44,7 +44,7 @@ namespace mongo {
*/
class ConflictPlaceholderNode : public UpdateLeafNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final {
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final {
return Status::OK();
}
diff --git a/src/mongo/db/update/current_date_node.cpp b/src/mongo/db/update/current_date_node.cpp
index 4d6075a65f7..057ce2c1779 100644
--- a/src/mongo/db/update/current_date_node.cpp
+++ b/src/mongo/db/update/current_date_node.cpp
@@ -51,7 +51,8 @@ void setValue(mutablebson::Element* element, bool typeIsDate) {
}
} // namespace
-Status CurrentDateNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status CurrentDateNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
if (modExpr.type() == BSONType::Bool) {
diff --git a/src/mongo/db/update/current_date_node.h b/src/mongo/db/update/current_date_node.h
index bac2eb5c857..369ae7037ee 100644
--- a/src/mongo/db/update/current_date_node.h
+++ b/src/mongo/db/update/current_date_node.h
@@ -38,7 +38,7 @@ namespace mongo {
*/
class CurrentDateNode : public ModifierNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<CurrentDateNode>(*this);
diff --git a/src/mongo/db/update/current_date_node_test.cpp b/src/mongo/db/update/current_date_node_test.cpp
index 689ada219f6..e9cb5d5a8c8 100644
--- a/src/mongo/db/update/current_date_node_test.cpp
+++ b/src/mongo/db/update/current_date_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -46,86 +47,86 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(CurrentDateNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$currentDate: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- node.init(update["$currentDate"].embeddedObject().firstElement(), collator).ignore();
+ node.init(update["$currentDate"].embeddedObject().firstElement(), expCtx).ignore();
}
TEST(CurrentDateNodeTest, InitWithNonBoolNonObjectFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: 0}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithTrueSucceeds) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: true}}");
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithFalseSucceeds) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: false}}");
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithoutTypeFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {}}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithNonStringTypeFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$type: 1}}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithBadValueTypeFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$type: 'bad'}}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithTypeDateSucceeds) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$type: 'date'}}}");
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithTypeTimestampSucceeds) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$type: 'timestamp'}}}");
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithExtraFieldBeforeFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$bad: 1, $type: 'date'}}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST(CurrentDateNodeTest, InitWithExtraFieldAfterFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto update = fromjson("{$currentDate: {a: {$type: 'date', $bad: 1}}}");
CurrentDateNode node;
- ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_NOT_OK(node.init(update["$currentDate"]["a"], expCtx));
}
TEST_F(CurrentDateNodeTest, ApplyTrue) {
auto update = fromjson("{$currentDate: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -147,9 +148,9 @@ TEST_F(CurrentDateNodeTest, ApplyTrue) {
TEST_F(CurrentDateNodeTest, ApplyFalse) {
auto update = fromjson("{$currentDate: {a: false}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -171,9 +172,9 @@ TEST_F(CurrentDateNodeTest, ApplyFalse) {
TEST_F(CurrentDateNodeTest, ApplyDate) {
auto update = fromjson("{$currentDate: {a: {$type: 'date'}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -195,9 +196,9 @@ TEST_F(CurrentDateNodeTest, ApplyDate) {
TEST_F(CurrentDateNodeTest, ApplyTimestamp) {
auto update = fromjson("{$currentDate: {a: {$type: 'timestamp'}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -219,9 +220,9 @@ TEST_F(CurrentDateNodeTest, ApplyTimestamp) {
TEST_F(CurrentDateNodeTest, ApplyFieldDoesNotExist) {
auto update = fromjson("{$currentDate: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -243,9 +244,9 @@ TEST_F(CurrentDateNodeTest, ApplyFieldDoesNotExist) {
TEST_F(CurrentDateNodeTest, ApplyIndexesNotAffected) {
auto update = fromjson("{$currentDate: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
@@ -267,9 +268,9 @@ TEST_F(CurrentDateNodeTest, ApplyIndexesNotAffected) {
TEST_F(CurrentDateNodeTest, ApplyNoIndexDataOrLogBuilder) {
auto update = fromjson("{$currentDate: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
CurrentDateNode node;
- ASSERT_OK(node.init(update["$currentDate"]["a"], collator));
+ ASSERT_OK(node.init(update["$currentDate"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathTaken("a");
diff --git a/src/mongo/db/update/path_support_test.cpp b/src/mongo/db/update/path_support_test.cpp
index 3de5e8eff00..cb397c01bd1 100644
--- a/src/mongo/db/update/path_support_test.cpp
+++ b/src/mongo/db/update/path_support_test.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/mongoutils/str.h"
@@ -588,8 +589,8 @@ TEST_F(ArrayDoc, CreatePathAtFailsIfElemFoundIsArrayAndIdxFoundFieldIsNonNumeric
//
static MatchExpression* makeExpr(const BSONObj& exprBSON) {
- const CollatorInterface* collator = nullptr;
- return MatchExpressionParser::parse(exprBSON, collator).getValue().release();
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ return MatchExpressionParser::parse(exprBSON, std::move(expCtx)).getValue().release();
}
static void assertContains(const EqualityMatches& equalities, const BSONObj& wrapped) {
diff --git a/src/mongo/db/update/pop_node.cpp b/src/mongo/db/update/pop_node.cpp
index 96c495c29a5..412e913455b 100644
--- a/src/mongo/db/update/pop_node.cpp
+++ b/src/mongo/db/update/pop_node.cpp
@@ -34,7 +34,7 @@
namespace mongo {
-Status PopNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status PopNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
auto popVal = MatchExpressionParser::parseIntegerElementToLong(modExpr);
if (!popVal.isOK()) {
return popVal.getStatus();
diff --git a/src/mongo/db/update/pop_node.h b/src/mongo/db/update/pop_node.h
index 2b8d99ce1e7..aaeba88b439 100644
--- a/src/mongo/db/update/pop_node.h
+++ b/src/mongo/db/update/pop_node.h
@@ -35,7 +35,7 @@ namespace mongo {
class PopNode final : public ModifierNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
ModifyResult updateExistingElement(mutablebson::Element* element,
std::shared_ptr<FieldRef> elementPath) const final;
diff --git a/src/mongo/db/update/pop_node_test.cpp b/src/mongo/db/update/pop_node_test.cpp
index 8057331fab5..6f431fdb0fa 100644
--- a/src/mongo/db/update/pop_node_test.cpp
+++ b/src/mongo/db/update/pop_node_test.cpp
@@ -32,6 +32,7 @@
#include "mongo/bson/json.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -44,67 +45,67 @@ using PopNodeTest = UpdateNodeTest;
TEST(PopNodeTest, InitSucceedsPositiveOne) {
auto update = fromjson("{$pop: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a"], expCtx));
ASSERT_FALSE(popNode.popFromFront());
}
TEST(PopNodeTest, InitSucceedsNegativeOne) {
auto update = fromjson("{$pop: {a: -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a"], expCtx));
ASSERT_TRUE(popNode.popFromFront());
}
TEST(PopNodeTest, InitFailsOnePointOne) {
auto update = fromjson("{$pop: {a: 1.1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST(PopNodeTest, InitFailsZero) {
auto update = fromjson("{$pop: {a: 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST(PopNodeTest, InitFailsString) {
auto update = fromjson("{$pop: {a: 'foo'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST(PopNodeTest, InitFailsNestedObject) {
auto update = fromjson("{$pop: {a: {b: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST(PopNodeTest, InitFailsNestedArray) {
auto update = fromjson("{$pop: {a: [{b: 1}]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST(PopNodeTest, InitFailsBool) {
auto update = fromjson("{$pop: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], collator));
+ ASSERT_EQ(ErrorCodes::FailedToParse, popNode.init(update["$pop"]["a"], expCtx));
}
TEST_F(PopNodeTest, NoopWhenFirstPathComponentDoesNotExist) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{b: [1, 2, 3]}"));
setPathToCreate("a.b");
@@ -118,9 +119,9 @@ TEST_F(PopNodeTest, NoopWhenFirstPathComponentDoesNotExist) {
TEST_F(PopNodeTest, NoopWhenPathPartiallyExists) {
auto update = fromjson("{$pop: {'a.b.c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b.c"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b.c"], expCtx));
mmb::Document doc(fromjson("{a: {}}"));
setPathToCreate("b.c");
@@ -135,9 +136,9 @@ TEST_F(PopNodeTest, NoopWhenPathPartiallyExists) {
TEST_F(PopNodeTest, NoopWhenNumericalPathComponentExceedsArrayLength) {
auto update = fromjson("{$pop: {'a.0': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.0"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.0"], expCtx));
mmb::Document doc(fromjson("{a: []}"));
setPathToCreate("0");
@@ -152,9 +153,9 @@ TEST_F(PopNodeTest, NoopWhenNumericalPathComponentExceedsArrayLength) {
TEST_F(PopNodeTest, ThrowsWhenPathIsBlockedByAScalar) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: 'foo'}"));
setPathToCreate("b");
@@ -171,9 +172,9 @@ DEATH_TEST_F(PopNodeTest,
NonOkElementWhenPathExistsIsFatal,
"Invariant failure applyParams.element.ok()") {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
setPathTaken("a.b");
@@ -183,9 +184,9 @@ DEATH_TEST_F(PopNodeTest,
TEST_F(PopNodeTest, ThrowsWhenPathExistsButDoesNotContainAnArray) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: 'foo'}}"));
setPathTaken("a.b");
@@ -198,9 +199,9 @@ TEST_F(PopNodeTest, ThrowsWhenPathExistsButDoesNotContainAnArray) {
TEST_F(PopNodeTest, NoopWhenPathContainsAnEmptyArray) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: []}}"));
setPathTaken("a.b");
@@ -214,9 +215,9 @@ TEST_F(PopNodeTest, NoopWhenPathContainsAnEmptyArray) {
TEST_F(PopNodeTest, PopsSingleElementFromTheBack) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_FALSE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1]}}"));
@@ -231,9 +232,9 @@ TEST_F(PopNodeTest, PopsSingleElementFromTheBack) {
TEST_F(PopNodeTest, PopsSingleElementFromTheFront) {
auto update = fromjson("{$pop: {'a.b': -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_TRUE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [[1]]}}"));
@@ -248,9 +249,9 @@ TEST_F(PopNodeTest, PopsSingleElementFromTheFront) {
TEST_F(PopNodeTest, PopsFromTheBackOfMultiElementArray) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_FALSE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
@@ -265,9 +266,9 @@ TEST_F(PopNodeTest, PopsFromTheBackOfMultiElementArray) {
TEST_F(PopNodeTest, PopsFromTheFrontOfMultiElementArray) {
auto update = fromjson("{$pop: {'a.b': -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_TRUE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
@@ -282,9 +283,9 @@ TEST_F(PopNodeTest, PopsFromTheFrontOfMultiElementArray) {
TEST_F(PopNodeTest, PopsFromTheFrontOfMultiElementArrayWithoutAffectingIndexes) {
auto update = fromjson("{$pop: {'a.b': -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_TRUE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
@@ -299,9 +300,9 @@ TEST_F(PopNodeTest, PopsFromTheFrontOfMultiElementArrayWithoutAffectingIndexes)
TEST_F(PopNodeTest, SucceedsWithNullUpdateIndexData) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_FALSE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
@@ -315,9 +316,9 @@ TEST_F(PopNodeTest, SucceedsWithNullUpdateIndexData) {
TEST_F(PopNodeTest, SucceedsWithNullLogBuilder) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
ASSERT_FALSE(popNode.popFromFront());
mmb::Document doc(fromjson("{a: {b: [1, 2, 3]}}"));
@@ -332,9 +333,9 @@ TEST_F(PopNodeTest, SucceedsWithNullLogBuilder) {
TEST_F(PopNodeTest, ThrowsWhenPathIsImmutable) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: [0]}}"));
setPathTaken("a.b");
@@ -354,9 +355,9 @@ TEST_F(PopNodeTest, ThrowsWhenPathIsPrefixOfImmutable) {
// array in it.
auto update = fromjson("{$pop: {'a': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a"], expCtx));
mmb::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -371,9 +372,9 @@ TEST_F(PopNodeTest, ThrowsWhenPathIsPrefixOfImmutable) {
TEST_F(PopNodeTest, ThrowsWhenPathIsSuffixOfImmutable) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: [0]}}"));
setPathTaken("a.b");
@@ -388,9 +389,9 @@ TEST_F(PopNodeTest, ThrowsWhenPathIsSuffixOfImmutable) {
TEST_F(PopNodeTest, NoopOnImmutablePathSucceeds) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PopNode popNode;
- ASSERT_OK(popNode.init(update["$pop"]["a.b"], collator));
+ ASSERT_OK(popNode.init(update["$pop"]["a.b"], expCtx));
mmb::Document doc(fromjson("{a: {b: []}}"));
setPathTaken("a.b");
diff --git a/src/mongo/db/update/pull_node.cpp b/src/mongo/db/update/pull_node.cpp
index 9ef4e02724b..b712e2ece4e 100644
--- a/src/mongo/db/update/pull_node.cpp
+++ b/src/mongo/db/update/pull_node.cpp
@@ -41,8 +41,8 @@ namespace mongo {
*/
class PullNode::ObjectMatcher final : public PullNode::ElementMatcher {
public:
- ObjectMatcher(BSONObj matchCondition, const CollatorInterface* collator)
- : _matchExpr(matchCondition, collator) {}
+ ObjectMatcher(BSONObj matchCondition, const boost::intrusive_ptr<ExpressionContext>& expCtx)
+ : _matchExpr(matchCondition, expCtx) {}
std::unique_ptr<ElementMatcher> clone() const final {
return stdx::make_unique<ObjectMatcher>(*this);
@@ -73,8 +73,9 @@ private:
*/
class PullNode::WrappedObjectMatcher final : public PullNode::ElementMatcher {
public:
- WrappedObjectMatcher(BSONElement matchCondition, const CollatorInterface* collator)
- : _matchExpr(matchCondition.wrap(""), collator) {}
+ WrappedObjectMatcher(BSONElement matchCondition,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx)
+ : _matchExpr(matchCondition.wrap(""), expCtx) {}
std::unique_ptr<ElementMatcher> clone() const final {
return stdx::make_unique<WrappedObjectMatcher>(*this);
@@ -119,18 +120,18 @@ private:
const CollatorInterface* _collator;
};
-Status PullNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status PullNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
try {
if (modExpr.type() == mongo::Object &&
!MatchExpressionParser::parsePathAcceptingKeyword(
modExpr.embeddedObject().firstElement())) {
- _matcher = stdx::make_unique<ObjectMatcher>(modExpr.embeddedObject(), collator);
+ _matcher = stdx::make_unique<ObjectMatcher>(modExpr.embeddedObject(), expCtx);
} else if (modExpr.type() == mongo::Object || modExpr.type() == mongo::RegEx) {
- _matcher = stdx::make_unique<WrappedObjectMatcher>(modExpr, collator);
+ _matcher = stdx::make_unique<WrappedObjectMatcher>(modExpr, expCtx);
} else {
- _matcher = stdx::make_unique<EqualityMatcher>(modExpr, collator);
+ _matcher = stdx::make_unique<EqualityMatcher>(modExpr, expCtx->getCollator());
}
} catch (AssertionException& exception) {
return exception.toStatus();
diff --git a/src/mongo/db/update/pull_node.h b/src/mongo/db/update/pull_node.h
index 346c6da7f04..c12019686e5 100644
--- a/src/mongo/db/update/pull_node.h
+++ b/src/mongo/db/update/pull_node.h
@@ -42,7 +42,7 @@ namespace mongo {
*/
class PullNode final : public ArrayCullingNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<PullNode>(*this);
diff --git a/src/mongo/db/update/pull_node_test.cpp b/src/mongo/db/update/pull_node_test.cpp
index 2fc996d05f1..744abd739f4 100644
--- a/src/mongo/db/update/pull_node_test.cpp
+++ b/src/mongo/db/update/pull_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
@@ -47,36 +48,36 @@ using mongo::mutablebson::countChildren;
TEST(PullNodeTest, InitWithBadMatchExpressionFails) {
auto update = fromjson("{$pull: {a: {b: {$foo: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullNodeTest, InitWithBadTopLevelOperatorFails) {
auto update = fromjson("{$pull: {a: {$foo: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullNodeTest, InitWithTextFails) {
auto update = fromjson("{$pull: {a: {$text: {$search: 'str'}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
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;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -84,9 +85,9 @@ TEST(PullNodeTest, InitWithWhereFails) {
TEST(PullNodeTest, InitWithGeoNearElemFails) {
auto update =
fromjson("{$pull: {a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -94,36 +95,36 @@ TEST(PullNodeTest, InitWithGeoNearElemFails) {
TEST(PullNodeTest, InitWithGeoNearObjectFails) {
auto update = fromjson(
"{$pull: {a: {b: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullNodeTest, InitWithExprElemFails) {
auto update = fromjson("{$pull: {a: {$expr: {$eq: [5, 5]}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullNodeTest, InitWithExprObjectFails) {
auto update = fromjson("{$pull: {a: {$expr: {$eq: ['$a', {$literal: {b: 5}}]}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- auto status = node.init(update["$pull"]["a"], collator);
+ auto status = node.init(update["$pull"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST_F(PullNodeTest, TargetNotFound) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -138,9 +139,9 @@ TEST_F(PullNodeTest, TargetNotFound) {
TEST_F(PullNodeTest, ApplyToStringFails) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 'foo'}"));
setPathTaken("a");
@@ -153,9 +154,9 @@ TEST_F(PullNodeTest, ApplyToStringFails) {
TEST_F(PullNodeTest, ApplyToObjectFails) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {foo: 'bar'}}"));
setPathTaken("a");
@@ -168,9 +169,9 @@ TEST_F(PullNodeTest, ApplyToObjectFails) {
TEST_F(PullNodeTest, ApplyToNonViablePathFails) {
auto update = fromjson("{$pull : {'a.b': {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathToCreate("b");
@@ -185,9 +186,9 @@ TEST_F(PullNodeTest, ApplyToNonViablePathFails) {
TEST_F(PullNodeTest, ApplyToMissingElement) {
auto update = fromjson("{$pull: {'a.b.c.d': {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b.c.d"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b.c.d"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: {}}}}"));
setPathToCreate("d");
@@ -203,9 +204,9 @@ TEST_F(PullNodeTest, ApplyToMissingElement) {
TEST_F(PullNodeTest, ApplyToEmptyArray) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -220,9 +221,9 @@ TEST_F(PullNodeTest, ApplyToEmptyArray) {
TEST_F(PullNodeTest, ApplyToArrayMatchingNone) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [2, 3, 4, 5]}"));
setPathTaken("a");
@@ -237,9 +238,9 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingNone) {
TEST_F(PullNodeTest, ApplyToArrayMatchingOne) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3]}"));
setPathTaken("a");
@@ -254,9 +255,9 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingOne) {
TEST_F(PullNodeTest, ApplyToArrayMatchingSeveral) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 0, 2, 0, 3, 0, 4, 0, 5]}"));
setPathTaken("a");
@@ -271,9 +272,9 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingSeveral) {
TEST_F(PullNodeTest, ApplyToArrayMatchingAll) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, -1, -2, -3, -4, -5]}"));
setPathTaken("a");
@@ -288,9 +289,9 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingAll) {
TEST_F(PullNodeTest, ApplyNoIndexDataNoLogBuilder) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3]}"));
setPathTaken("a");
@@ -307,8 +308,10 @@ TEST_F(PullNodeTest, ApplyWithCollation) {
// reverse of the "abc" string.
auto update = fromjson("{$pull : {a: {$gt: 'abc'}}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['zaa', 'zcc', 'zbb', 'zee']}"));
setPathTaken("a");
@@ -324,8 +327,10 @@ TEST_F(PullNodeTest, ApplyWithCollation) {
TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectNonStringMatches) {
auto update = fromjson("{$pull : {a: {$lt: 1}}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [2, 1, 0, -1, -2, -3]}"));
setPathTaken("a");
@@ -341,8 +346,10 @@ TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectNonStringMatches) {
TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectRegexMatches) {
auto update = fromjson("{$pull : {a: /a/}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}"));
setPathTaken("a");
@@ -358,8 +365,10 @@ TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectRegexMatches) {
TEST_F(PullNodeTest, ApplyStringLiteralMatchWithCollation) {
auto update = fromjson("{$pull : {a: 'c'}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}"));
setPathTaken("a");
@@ -375,8 +384,10 @@ TEST_F(PullNodeTest, ApplyStringLiteralMatchWithCollation) {
TEST_F(PullNodeTest, ApplyCollationDoesNotAffectNumberLiteralMatches) {
auto update = fromjson("{$pull : {a: 99}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['a', 99, 'b', 2, 'c', 99, 'd']}"));
setPathTaken("a");
@@ -392,8 +403,8 @@ TEST_F(PullNodeTest, ApplyCollationDoesNotAffectNumberLiteralMatches) {
TEST_F(PullNodeTest, ApplyStringMatchAfterSetCollator) {
auto update = fromjson("{$pull : {a: 'c'}}");
PullNode node;
- const CollatorInterface* collator = nullptr;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
// First without a collator.
mutablebson::Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }"));
@@ -420,8 +431,8 @@ TEST_F(PullNodeTest, ApplyStringMatchAfterSetCollator) {
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));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
// First without a collator.
mutablebson::Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }"));
@@ -448,8 +459,8 @@ TEST_F(PullNodeTest, ApplyElementMatchAfterSetCollator) {
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));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
// First without a collator.
mutablebson::Document doc(fromjson("{a : [{b: 'w'}, {b: 'x'}, {b: 'y'}, {b: 'z'}]}"));
@@ -476,8 +487,8 @@ TEST_F(PullNodeTest, ApplyObjectMatchAfterSetCollator) {
TEST_F(PullNodeTest, SetCollatorDoesNotAffectClone) {
auto update = fromjson("{$pull : {a: 'c'}}");
PullNode node;
- const CollatorInterface* collator = nullptr;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
auto cloneNode = node.clone();
@@ -510,9 +521,9 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching1) {
" {'y': {$exists: true }},"
" {'z' : {$exists : true}} "
"]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}"));
setPathTaken("a.b");
@@ -527,9 +538,9 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching1) {
TEST_F(PullNodeTest, ApplyComplexDocAndMatching2) {
auto update = fromjson("{$pull: {'a.b': {'y': {$exists: true}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}"));
setPathTaken("a.b");
@@ -544,9 +555,9 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching2) {
TEST_F(PullNodeTest, ApplyComplexDocAndMatching3) {
auto update = fromjson("{$pull: {'a.b': {$in: [{x: 1}, {y: 'y'}]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}"));
setPathTaken("a.b");
@@ -562,8 +573,10 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching3) {
TEST_F(PullNodeTest, ApplyFullPredicateWithCollation) {
auto update = fromjson("{$pull: {'a.b': {x: 'blah'}}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a.b"], &collator));
+ ASSERT_OK(node.init(update["$pull"]["a.b"], expCtx));
mutablebson::Document doc(
fromjson("{a: {b: [{x: 'foo', y: 1}, {x: 'bar', y: 2}, {x: 'baz', y: 3}]}}"));
@@ -579,9 +592,9 @@ TEST_F(PullNodeTest, ApplyFullPredicateWithCollation) {
TEST_F(PullNodeTest, ApplyScalarValueMod) {
auto update = fromjson("{$pull: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 2, 1, 2, 1, 2]}"));
setPathTaken("a");
@@ -596,9 +609,9 @@ TEST_F(PullNodeTest, ApplyScalarValueMod) {
TEST_F(PullNodeTest, ApplyObjectValueMod) {
auto update = fromjson("{$pull: {a: {y: 2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [{x: 1}, {y: 2}, {x: 1}, {y: 2}]}"));
setPathTaken("a");
@@ -613,9 +626,9 @@ TEST_F(PullNodeTest, ApplyObjectValueMod) {
TEST_F(PullNodeTest, DocumentationExample1) {
auto update = fromjson("{$pull: {flags: 'msr'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["flags"], collator));
+ ASSERT_OK(node.init(update["$pull"]["flags"], expCtx));
mutablebson::Document doc(
fromjson("{flags: ['vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce']}"));
@@ -632,9 +645,9 @@ TEST_F(PullNodeTest, DocumentationExample1) {
TEST_F(PullNodeTest, DocumentationExample2a) {
auto update = fromjson("{$pull: {votes: 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["votes"], collator));
+ ASSERT_OK(node.init(update["$pull"]["votes"], expCtx));
mutablebson::Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}"));
setPathTaken("votes");
@@ -649,9 +662,9 @@ TEST_F(PullNodeTest, DocumentationExample2a) {
TEST_F(PullNodeTest, DocumentationExample2b) {
auto update = fromjson("{$pull: {votes: {$gt: 6}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["votes"], collator));
+ ASSERT_OK(node.init(update["$pull"]["votes"], expCtx));
mutablebson::Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}"));
setPathTaken("votes");
@@ -666,9 +679,9 @@ TEST_F(PullNodeTest, DocumentationExample2b) {
TEST_F(PullNodeTest, ApplyPullWithObjectValueToArrayWithNonObjectValue) {
auto update = fromjson("{$pull: {a: {x: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [{x: 1}, 2]}"));
setPathTaken("a");
@@ -683,9 +696,9 @@ TEST_F(PullNodeTest, ApplyPullWithObjectValueToArrayWithNonObjectValue) {
TEST_F(PullNodeTest, CannotModifyImmutableField) {
auto update = fromjson("{$pull: {'_id.a': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["_id.a"], collator));
+ ASSERT_OK(node.init(update["$pull"]["_id.a"], expCtx));
mutablebson::Document doc(fromjson("{_id: {a: [0, 1, 2]}}"));
setPathTaken("_id.a");
@@ -699,9 +712,9 @@ TEST_F(PullNodeTest, CannotModifyImmutableField) {
TEST_F(PullNodeTest, SERVER_3988) {
auto update = fromjson("{$pull: {y: /yz/}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullNode node;
- ASSERT_OK(node.init(update["$pull"]["y"], collator));
+ ASSERT_OK(node.init(update["$pull"]["y"], expCtx));
mutablebson::Document doc(fromjson("{x: 1, y: [2, 3, 4, 'abc', 'xyz']}"));
setPathTaken("y");
diff --git a/src/mongo/db/update/pullall_node.cpp b/src/mongo/db/update/pullall_node.cpp
index afdceaac3d5..ec54796eb3e 100644
--- a/src/mongo/db/update/pullall_node.cpp
+++ b/src/mongo/db/update/pullall_node.cpp
@@ -61,7 +61,8 @@ private:
const CollatorInterface* _collator;
};
-Status PullAllNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status PullAllNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
if (modExpr.type() != Array) {
@@ -70,7 +71,7 @@ Status PullAllNode::init(BSONElement modExpr, const CollatorInterface* collator)
<< typeName(modExpr.type()));
}
- _matcher = stdx::make_unique<SetMatcher>(modExpr.Array(), collator);
+ _matcher = stdx::make_unique<SetMatcher>(modExpr.Array(), expCtx->getCollator());
return Status::OK();
}
diff --git a/src/mongo/db/update/pullall_node.h b/src/mongo/db/update/pullall_node.h
index b1d960976ed..0a552323f19 100644
--- a/src/mongo/db/update/pullall_node.h
+++ b/src/mongo/db/update/pullall_node.h
@@ -42,7 +42,7 @@ namespace mongo {
class PullAllNode final : public ArrayCullingNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<PullAllNode>(*this);
diff --git a/src/mongo/db/update/pullall_node_test.cpp b/src/mongo/db/update/pullall_node_test.cpp
index 03ba5290d62..edcc22370ed 100644
--- a/src/mongo/db/update/pullall_node_test.cpp
+++ b/src/mongo/db/update/pullall_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
@@ -47,45 +48,45 @@ using mongo::mutablebson::countChildren;
TEST(PullAllNodeTest, InitWithIntFails) {
auto update = fromjson("{$pullAll: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- auto status = node.init(update["$pullAll"]["a"], collator);
+ auto status = node.init(update["$pullAll"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullAllNodeTest, InitWithStringFails) {
auto update = fromjson("{$pullAll: {a: 'test'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- auto status = node.init(update["$pullAll"]["a"], collator);
+ auto status = node.init(update["$pullAll"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullAllNodeTest, InitWithObjectFails) {
auto update = fromjson("{$pullAll: {a: {}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- auto status = node.init(update["$pullAll"]["a"], collator);
+ auto status = node.init(update["$pullAll"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PullAllNodeTest, InitWithBoolFails) {
auto update = fromjson("{$pullAll: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- auto status = node.init(update["$pullAll"]["a"], collator);
+ auto status = node.init(update["$pullAll"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST_F(PullAllNodeTest, TargetNotFound) {
auto update = fromjson("{$pullAll : {b: [1]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["b"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["b"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathToCreate("b");
@@ -100,9 +101,9 @@ TEST_F(PullAllNodeTest, TargetNotFound) {
TEST_F(PullAllNodeTest, TargetArrayElementNotFound) {
auto update = fromjson("{$pullAll : {'a.2': [1]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a.2"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a.2"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 2]}"));
setPathToCreate("2");
@@ -118,9 +119,9 @@ TEST_F(PullAllNodeTest, TargetArrayElementNotFound) {
TEST_F(PullAllNodeTest, ApplyToNonArrayFails) {
auto update = fromjson("{$pullAll : {'a.0': [1, 2]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a.0"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a.0"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 2]}"));
setPathTaken("a.0");
@@ -133,9 +134,9 @@ TEST_F(PullAllNodeTest, ApplyToNonArrayFails) {
TEST_F(PullAllNodeTest, ApplyWithSingleNumber) {
auto update = fromjson("{$pullAll : {a: [1]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -150,9 +151,9 @@ TEST_F(PullAllNodeTest, ApplyWithSingleNumber) {
TEST_F(PullAllNodeTest, ApplyNoIndexDataNoLogBuilder) {
auto update = fromjson("{$pullAll : {a: [1]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -166,9 +167,9 @@ TEST_F(PullAllNodeTest, ApplyNoIndexDataNoLogBuilder) {
TEST_F(PullAllNodeTest, ApplyWithElementNotPresentInArray) {
auto update = fromjson("{$pullAll : {a: ['r']}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -183,9 +184,9 @@ TEST_F(PullAllNodeTest, ApplyWithElementNotPresentInArray) {
TEST_F(PullAllNodeTest, ApplyWithWithTwoElements) {
auto update = fromjson("{$pullAll : {a: [1, 'a']}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -200,9 +201,9 @@ TEST_F(PullAllNodeTest, ApplyWithWithTwoElements) {
TEST_F(PullAllNodeTest, ApplyWithAllArrayElements) {
auto update = fromjson("{$pullAll : {a: [1, 'a', {r: 1, b: 2}]}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -217,9 +218,9 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElements) {
TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsButOutOfOrder) {
auto update = fromjson("{$pullAll : {a: [{r: 1, b: 2}, 1, 'a']}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -234,9 +235,9 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsButOutOfOrder) {
TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsAndThenSome) {
auto update = fromjson("{$pullAll : {a: [2, 3, 1, 'r', {r: 1, b: 2}, 'a']}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}"));
setPathTaken("a");
@@ -252,8 +253,10 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsAndThenSome) {
TEST_F(PullAllNodeTest, ApplyWithCollator) {
auto update = fromjson("{$pullAll : {a: ['FOO', 'BAR']}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kToLowerString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], &collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['foo', 'bar', 'baz']}"));
setPathTaken("a");
@@ -268,9 +271,9 @@ TEST_F(PullAllNodeTest, ApplyWithCollator) {
TEST_F(PullAllNodeTest, ApplyAfterSetCollator) {
auto update = fromjson("{$pullAll : {a: ['FOO', 'BAR']}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PullAllNode node;
- ASSERT_OK(node.init(update["$pullAll"]["a"], collator));
+ ASSERT_OK(node.init(update["$pullAll"]["a"], expCtx));
// First without a collator.
mutablebson::Document doc(fromjson("{a: ['foo', 'bar', 'baz']}"));
diff --git a/src/mongo/db/update/push_node.cpp b/src/mongo/db/update/push_node.cpp
index 84748ae7caa..ac235e722f9 100644
--- a/src/mongo/db/update/push_node.cpp
+++ b/src/mongo/db/update/push_node.cpp
@@ -82,7 +82,7 @@ Status checkSortClause(const BSONObj& sortObject) {
} // namespace
-Status PushNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status PushNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
if (modExpr.type() == BSONType::Object && modExpr[kEachClauseName]) {
@@ -148,14 +148,14 @@ Status PushNode::init(BSONElement modExpr, const CollatorInterface* collator) {
auto status = checkSortClause(sortClause.embeddedObject());
if (status.isOK()) {
- _sort = PatternElementCmp(sortClause.embeddedObject(), collator);
+ _sort = PatternElementCmp(sortClause.embeddedObject(), expCtx->getCollator());
} else {
return status;
}
} else if (sortClause.isNumber()) {
double orderVal = sortClause.Number();
if (orderVal == -1 || orderVal == 1) {
- _sort = PatternElementCmp(BSON("" << orderVal), collator);
+ _sort = PatternElementCmp(BSON("" << orderVal), expCtx->getCollator());
} else {
return Status(ErrorCodes::BadValue,
"The $sort element value must be either 1 or -1");
diff --git a/src/mongo/db/update/push_node.h b/src/mongo/db/update/push_node.h
index 66e93d03393..cf636820d8a 100644
--- a/src/mongo/db/update/push_node.h
+++ b/src/mongo/db/update/push_node.h
@@ -43,7 +43,7 @@ public:
PushNode()
: _slice(std::numeric_limits<long long>::max()),
_position(std::numeric_limits<long long>::max()) {}
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<PushNode>(*this);
diff --git a/src/mongo/db/update/push_node_test.cpp b/src/mongo/db/update/push_node_test.cpp
index 3525a4b8767..6eefb09bd53 100644
--- a/src/mongo/db/update/push_node_test.cpp
+++ b/src/mongo/db/update/push_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
@@ -47,123 +48,123 @@ using mongo::mutablebson::countChildren;
TEST(PushNodeTest, EachClauseWithNonArrayObjectFails) {
auto update = fromjson("{$push: {x: {$each: {'0': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, EachClauseWithPrimitiveFails) {
auto update = fromjson("{$push: {x: {$each: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, PositionClauseWithObjectFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $position: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, PositionClauseWithNonIntegerFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $position: -2.1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, PositionClauseWithIntegerDoubleSucceeds) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $position: -2.0}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_OK(status);
}
TEST(PushNodeTest, SliceClauseWithObjectFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $slice: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SliceClauseWithNonIntegerFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $slice: -2.1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SliceClauseWithIntegerDoubleSucceeds) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $slice: 2.0}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["x"], collator));
+ ASSERT_OK(node.init(update["$push"]["x"], expCtx));
}
TEST(PushNodeTest, SliceClauseWithArrayFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $slice: [1, 2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SliceClauseWithStringFails) {
auto update = fromjson("{$push: {x: {$each: [1, 2], $slice: '-1'}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SortClauseWithArrayFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: [{a: 1}]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SortClauseWithInvalidSortPatternFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {a: 100}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SortClauseWithEmptyPathFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {'': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SortClauseWithEmptyFieldNamesFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {'.': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -171,9 +172,9 @@ TEST(PushNodeTest, SortClauseWithEmptyFieldNamesFails) {
TEST(PushNodeTest, SortClauseWithEmptyFieldSuffixFails) {
auto update =
fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {'a.': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -181,9 +182,9 @@ TEST(PushNodeTest, SortClauseWithEmptyFieldSuffixFails) {
TEST(PushNodeTest, SortClauseWithEmptyFieldPrefixFails) {
auto update =
fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {'.b': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -191,27 +192,27 @@ TEST(PushNodeTest, SortClauseWithEmptyFieldPrefixFails) {
TEST(PushNodeTest, SortClauseWithEmptyFieldInfixFails) {
auto update =
fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {'a..b': 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, SortClauseWithEmptyObjectFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, PushEachWithInvalidClauseFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1}, {a: 2}], $xxx: -1, $sort: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -219,9 +220,9 @@ TEST(PushNodeTest, PushEachWithInvalidClauseFails) {
TEST(PushNodeTest, PushEachWithDuplicateSortClauseFails) {
auto update = fromjson(
"{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $sort: {a: 1}, $sort: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -229,9 +230,9 @@ TEST(PushNodeTest, PushEachWithDuplicateSortClauseFails) {
TEST(PushNodeTest, PushEachWithDuplicateSliceClauseFails) {
auto update =
fromjson("{$push: {x: {$each: [{a: 1},{a: 2}], $slice: -2.0, $slice: -2, $sort: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -239,27 +240,27 @@ TEST(PushNodeTest, PushEachWithDuplicateSliceClauseFails) {
TEST(PushNodeTest, PushEachWithDuplicateEachClauseFails) {
auto update =
fromjson("{$push: {x: {$each:[{a: 1}], $each:[{a: 2}], $slice: -3, $sort: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(PushNodeTest, PushEachWithDuplicatePositionClauseFails) {
auto update = fromjson("{$push: {x: {$each: [{a: 1}], $position: 1, $position: 2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- auto status = node.init(update["$push"]["x"], collator);
+ auto status = node.init(update["$push"]["x"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST_F(PushNodeTest, ApplyToNonArrayFails) {
auto update = fromjson("{$push: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: 1}"));
setPathTaken("a");
@@ -273,9 +274,9 @@ TEST_F(PushNodeTest, ApplyToNonArrayFails) {
TEST_F(PushNodeTest, ApplyToEmptyArray) {
auto update = fromjson("{$push: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -290,9 +291,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArray) {
TEST_F(PushNodeTest, ApplyToEmptyDocument) {
auto update = fromjson("{$push: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -307,9 +308,9 @@ TEST_F(PushNodeTest, ApplyToEmptyDocument) {
TEST_F(PushNodeTest, ApplyToArrayWithOneElement) {
auto update = fromjson("{$push: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -324,9 +325,9 @@ TEST_F(PushNodeTest, ApplyToArrayWithOneElement) {
TEST_F(PushNodeTest, ApplyToDottedPathElement) {
auto update = fromjson("{$push: {'choices.first.votes': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["choices.first.votes"], collator));
+ ASSERT_OK(node.init(update["$push"]["choices.first.votes"], expCtx));
mutablebson::Document doc(
fromjson("{_id : 1 , "
@@ -352,9 +353,9 @@ TEST_F(PushNodeTest, ApplyToDottedPathElement) {
TEST_F(PushNodeTest, ApplySimpleEachToEmptyArray) {
auto update = fromjson("{$push: {a: {$each: [1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -369,9 +370,9 @@ TEST_F(PushNodeTest, ApplySimpleEachToEmptyArray) {
TEST_F(PushNodeTest, ApplySimpleEachToEmptyDocument) {
auto update = fromjson("{$push: {a: {$each: [1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -386,9 +387,9 @@ TEST_F(PushNodeTest, ApplySimpleEachToEmptyDocument) {
TEST_F(PushNodeTest, ApplyMultipleEachToEmptyDocument) {
auto update = fromjson("{$push: {a: {$each: [1, 2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -403,9 +404,9 @@ TEST_F(PushNodeTest, ApplyMultipleEachToEmptyDocument) {
TEST_F(PushNodeTest, ApplySimpleEachToArrayWithOneElement) {
auto update = fromjson("{$push: {a: {$each: [1]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -420,9 +421,9 @@ TEST_F(PushNodeTest, ApplySimpleEachToArrayWithOneElement) {
TEST_F(PushNodeTest, ApplyMultipleEachToArrayWithOneElement) {
auto update = fromjson("{$push: {a: {$each: [1, 2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -437,9 +438,9 @@ TEST_F(PushNodeTest, ApplyMultipleEachToArrayWithOneElement) {
TEST_F(PushNodeTest, ApplyEmptyEachToEmptyArray) {
auto update = fromjson("{$push: {a: {$each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -454,9 +455,9 @@ TEST_F(PushNodeTest, ApplyEmptyEachToEmptyArray) {
TEST_F(PushNodeTest, ApplyEmptyEachToEmptyDocument) {
auto update = fromjson("{$push: {a: {$each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -471,9 +472,9 @@ TEST_F(PushNodeTest, ApplyEmptyEachToEmptyDocument) {
TEST_F(PushNodeTest, ApplyEmptyEachToArrayWithOneElement) {
auto update = fromjson("{$push: {a: {$each: []}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -488,9 +489,9 @@ TEST_F(PushNodeTest, ApplyEmptyEachToArrayWithOneElement) {
TEST_F(PushNodeTest, ApplyToArrayWithSlice) {
auto update = fromjson("{$push: {a: {$each: [2, -1], $slice: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3]}"));
setPathTaken("a");
@@ -505,9 +506,9 @@ TEST_F(PushNodeTest, ApplyToArrayWithSlice) {
TEST_F(PushNodeTest, ApplyWithNumericSort) {
auto update = fromjson("{$push: {a: {$each: [2, -1], $sort: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3]}"));
setPathTaken("a");
@@ -522,9 +523,9 @@ TEST_F(PushNodeTest, ApplyWithNumericSort) {
TEST_F(PushNodeTest, ApplyWithReverseNumericSort) {
auto update = fromjson("{$push: {a: {$each: [4, -1], $sort: -1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3]}"));
setPathTaken("a");
@@ -539,9 +540,9 @@ TEST_F(PushNodeTest, ApplyWithReverseNumericSort) {
TEST_F(PushNodeTest, ApplyWithMixedSort) {
auto update = fromjson("{$push: {a: {$each: [4, -1], $sort: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}"));
setPathTaken("a");
@@ -556,9 +557,9 @@ TEST_F(PushNodeTest, ApplyWithMixedSort) {
TEST_F(PushNodeTest, ApplyWithReverseMixedSort) {
auto update = fromjson("{$push: {a: {$each: [4, -1], $sort: -1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}"));
setPathTaken("a");
@@ -573,9 +574,9 @@ TEST_F(PushNodeTest, ApplyWithReverseMixedSort) {
TEST_F(PushNodeTest, ApplyWithEmbeddedFieldSort) {
auto update = fromjson("{$push: {a: {$each: [4, -1], $sort: {a: 1}}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}"));
setPathTaken("a");
@@ -591,8 +592,10 @@ TEST_F(PushNodeTest, ApplyWithEmbeddedFieldSort) {
TEST_F(PushNodeTest, ApplySortWithCollator) {
auto update = fromjson("{$push: {a: {$each: ['ha'], $sort: 1}}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], &collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['dd', 'fc', 'gb']}"));
setPathTaken("a");
@@ -607,9 +610,9 @@ TEST_F(PushNodeTest, ApplySortWithCollator) {
TEST_F(PushNodeTest, ApplySortAfterSetCollator) {
auto update = fromjson("{$push: {a: {$each: ['ha'], $sort: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: ['dd', 'fc', 'gb']}"));
setPathTaken("a");
@@ -666,9 +669,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithSliceValues) {
for (const auto& data : testDataList) {
auto update = BSON(
"$push" << BSON("a" << BSON("$each" << BSON_ARRAY(1) << "$slice" << data.sliceValue)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -698,9 +701,9 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithSliceValues) {
for (const auto& data : testDataList) {
auto update = BSON(
"$push" << BSON("a" << BSON("$each" << BSON_ARRAY(1) << "$slice" << data.sliceValue)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [2, 3]}"));
setPathTaken("a");
@@ -799,9 +802,9 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithSortAndSliceValues) {
<< data.sliceValue
<< "$sort"
<< data.sortOrder)));
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [{a: 2, b: 3}, {a: 3, b: 1}]}"));
setPathTaken("a");
@@ -813,9 +816,9 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithSortAndSliceValues) {
TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionZero) {
auto update = fromjson("{$push: {a: {$each: [1], $position: 0}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -830,9 +833,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionZero) {
TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionOne) {
auto update = fromjson("{$push: {a: {$each: [1], $position: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -847,9 +850,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionOne) {
TEST_F(PushNodeTest, ApplyToEmptyArrayWithLargePosition) {
auto update = fromjson("{$push: {a: {$each: [1], $position: 1000}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -864,9 +867,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithLargePosition) {
TEST_F(PushNodeTest, ApplyToSingletonArrayWithPositionZero) {
auto update = fromjson("{$push: {a: {$each: [1], $position: 0}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -881,9 +884,9 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithPositionZero) {
TEST_F(PushNodeTest, ApplyToSingletonArrayWithLargePosition) {
auto update = fromjson("{$push: {a: {$each: [1], $position: 1000}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -898,9 +901,9 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithLargePosition) {
TEST_F(PushNodeTest, ApplyToEmptyArrayWithNegativePosition) {
auto update = fromjson("{$push: {a: {$each: [1], $position: -1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathTaken("a");
@@ -915,9 +918,9 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithNegativePosition) {
TEST_F(PushNodeTest, ApplyToSingletonArrayWithNegativePosition) {
auto update = fromjson("{$push: {a: {$each: [1], $position: -1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0]}"));
setPathTaken("a");
@@ -932,9 +935,9 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithNegativePosition) {
TEST_F(PushNodeTest, ApplyToPopulatedArrayWithNegativePosition) {
auto update = fromjson("{$push: {a: {$each: [5], $position: -2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}"));
setPathTaken("a");
@@ -949,9 +952,9 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithNegativePosition) {
TEST_F(PushNodeTest, ApplyToPopulatedArrayWithOutOfBoundsNegativePosition) {
auto update = fromjson("{$push: {a: {$each: [5], $position: -1000}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}"));
setPathTaken("a");
@@ -966,9 +969,9 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithOutOfBoundsNegativePosition) {
TEST_F(PushNodeTest, ApplyMultipleElementsPushWithNegativePosition) {
auto update = fromjson("{$push: {a: {$each: [5, 6, 7], $position: -2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
PushNode node;
- ASSERT_OK(node.init(update["$push"]["a"], collator));
+ ASSERT_OK(node.init(update["$push"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}"));
setPathTaken("a");
diff --git a/src/mongo/db/update/rename_node.cpp b/src/mongo/db/update/rename_node.cpp
index fc50de42567..bae93e460de 100644
--- a/src/mongo/db/update/rename_node.cpp
+++ b/src/mongo/db/update/rename_node.cpp
@@ -60,7 +60,7 @@ public:
void setCollator(const CollatorInterface* collator) final {}
- Status init(BSONElement modExpr, const CollatorInterface* collator) {
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
return Status::OK();
}
@@ -99,7 +99,8 @@ private:
} // namespace
-Status RenameNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status RenameNode::init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
invariant(BSONType::String == modExpr.type());
diff --git a/src/mongo/db/update/rename_node.h b/src/mongo/db/update/rename_node.h
index 240ac32ebd4..d58b8e29e68 100644
--- a/src/mongo/db/update/rename_node.h
+++ b/src/mongo/db/update/rename_node.h
@@ -43,7 +43,7 @@ public:
* This init provides input validation on the source field (stored as the field name in
* "modExpr") and the destination field (stored as the value in "modExpr").
*/
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<RenameNode>(*this);
diff --git a/src/mongo/db/update/rename_node_test.cpp b/src/mongo/db/update/rename_node_test.cpp
index 1ac25292bab..e78ddf091d8 100644
--- a/src/mongo/db/update/rename_node_test.cpp
+++ b/src/mongo/db/update/rename_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -46,36 +47,36 @@ using mongo::mutablebson::countChildren;
TEST(RenameNodeTest, PositionalNotAllowedInFromField) {
auto update = fromjson("{$rename: {'a.$': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["a.$"], collator);
+ Status status = node.init(update["$rename"]["a.$"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(RenameNodeTest, PositionalNotAllowedInToField) {
auto update = fromjson("{$rename: {'a': 'b.$'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["a"], collator);
+ Status status = node.init(update["$rename"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(RenameNodeTest, ArrayFilterNotAllowedInFromField) {
auto update = fromjson("{$rename: {'a.$[i]': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["a.$[i]"], collator);
+ Status status = node.init(update["$rename"]["a.$[i]"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(RenameNodeTest, ArrayFilterNotAllowedInToField) {
auto update = fromjson("{$rename: {'a': 'b.$[i]'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["a"], collator);
+ Status status = node.init(update["$rename"]["a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
@@ -83,36 +84,36 @@ TEST(RenameNodeTest, ArrayFilterNotAllowedInToField) {
TEST(RenameNodeTest, MoveUpNotAllowed) {
auto update = fromjson("{$rename: {'b.a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["b.a"], collator);
+ Status status = node.init(update["$rename"]["b.a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(RenameNodeTest, MoveDownNotAllowed) {
auto update = fromjson("{$rename: {'b': 'b.a'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["b"], collator);
+ Status status = node.init(update["$rename"]["b"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST(RenameNodeTest, MoveToSelfNotAllowed) {
auto update = fromjson("{$rename: {'b.a': 'b.a'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- Status status = node.init(update["$rename"]["b.a"], collator);
+ Status status = node.init(update["$rename"]["b.a"], expCtx);
ASSERT_NOT_OK(status);
ASSERT_EQUALS(ErrorCodes::BadValue, status);
}
TEST_F(RenameNodeTest, SimpleNumberAtRoot) {
auto update = fromjson("{$rename: {'a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2}"));
setPathToCreate("b");
@@ -126,9 +127,9 @@ TEST_F(RenameNodeTest, SimpleNumberAtRoot) {
TEST_F(RenameNodeTest, ToExistsAtSameLevel) {
auto update = fromjson("{$rename: {'a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2, b: 1}"));
setPathTaken("b");
@@ -142,9 +143,9 @@ TEST_F(RenameNodeTest, ToExistsAtSameLevel) {
TEST_F(RenameNodeTest, ToAndFromHaveSameValue) {
auto update = fromjson("{$rename: {'a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2, b: 2}"));
setPathTaken("b");
@@ -158,9 +159,9 @@ TEST_F(RenameNodeTest, ToAndFromHaveSameValue) {
TEST_F(RenameNodeTest, FromDottedElement) {
auto update = fromjson("{$rename: {'a.c': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.c"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {c: {d: 6}}, b: 1}"));
setPathTaken("b");
@@ -174,9 +175,9 @@ TEST_F(RenameNodeTest, FromDottedElement) {
TEST_F(RenameNodeTest, RenameToExistingNestedFieldDoesNotReorderFields) {
auto update = fromjson("{$rename: {'c.d': 'a.b.c'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["c.d"], collator));
+ ASSERT_OK(node.init(update["$rename"]["c.d"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}"));
setPathTaken("a.b.c");
@@ -190,9 +191,9 @@ TEST_F(RenameNodeTest, RenameToExistingNestedFieldDoesNotReorderFields) {
TEST_F(RenameNodeTest, MissingCompleteTo) {
auto update = fromjson("{$rename: {a: 'c.r.d'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2, b: 1, c: {}}"));
setPathToCreate("r.d");
@@ -207,9 +208,9 @@ TEST_F(RenameNodeTest, MissingCompleteTo) {
TEST_F(RenameNodeTest, ToIsCompletelyMissing) {
auto update = fromjson("{$rename: {a: 'b.c.d'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2}"));
setPathToCreate("b.c.d");
@@ -223,9 +224,9 @@ TEST_F(RenameNodeTest, ToIsCompletelyMissing) {
TEST_F(RenameNodeTest, ToMissingDottedField) {
auto update = fromjson("{$rename: {a: 'b.c.d'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [{a:2, b:1}]}"));
setPathToCreate("b.c.d");
@@ -239,9 +240,9 @@ TEST_F(RenameNodeTest, ToMissingDottedField) {
TEST_F(RenameNodeTest, MoveIntoArray) {
auto update = fromjson("{$rename: {b: 'a.2'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["b"], collator));
+ ASSERT_OK(node.init(update["$rename"]["b"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}"));
setPathToCreate("2");
@@ -256,9 +257,9 @@ TEST_F(RenameNodeTest, MoveIntoArray) {
TEST_F(RenameNodeTest, MoveIntoArrayNoId) {
auto update = fromjson("{$rename: {b: 'a.2'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["b"], collator));
+ ASSERT_OK(node.init(update["$rename"]["b"], expCtx));
mutablebson::Document doc(fromjson("{a: [1, 2], b: 2}"));
setPathToCreate("2");
@@ -273,9 +274,9 @@ TEST_F(RenameNodeTest, MoveIntoArrayNoId) {
TEST_F(RenameNodeTest, MoveToArrayElement) {
auto update = fromjson("{$rename: {b: 'a.1'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["b"], collator));
+ ASSERT_OK(node.init(update["$rename"]["b"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}"));
setPathTaken("a.1");
@@ -289,9 +290,9 @@ TEST_F(RenameNodeTest, MoveToArrayElement) {
TEST_F(RenameNodeTest, MoveOutOfArray) {
auto update = fromjson("{$rename: {'a.0': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.0"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.0"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2]}"));
setPathToCreate("b");
@@ -305,9 +306,9 @@ TEST_F(RenameNodeTest, MoveOutOfArray) {
TEST_F(RenameNodeTest, MoveNonexistentEmbeddedFieldOut) {
auto update = fromjson("{$rename: {'a.a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.a"], expCtx));
mutablebson::Document doc(fromjson("{a: [{a: 1}, {b: 2}]}"));
setPathToCreate("b");
@@ -321,9 +322,9 @@ TEST_F(RenameNodeTest, MoveNonexistentEmbeddedFieldOut) {
TEST_F(RenameNodeTest, MoveEmbeddedFieldOutWithElementNumber) {
auto update = fromjson("{$rename: {'a.0.a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.0.a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.0.a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 'test_object', a: [{a: 1}, {b: 2}]}"));
setPathToCreate("b");
@@ -337,9 +338,9 @@ TEST_F(RenameNodeTest, MoveEmbeddedFieldOutWithElementNumber) {
TEST_F(RenameNodeTest, ReplaceArrayField) {
auto update = fromjson("{$rename: {a: 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2, b: []}"));
setPathTaken("b");
@@ -353,9 +354,9 @@ TEST_F(RenameNodeTest, ReplaceArrayField) {
TEST_F(RenameNodeTest, ReplaceWithArrayField) {
auto update = fromjson("{$rename: {a: 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [], b: 2}"));
setPathTaken("b");
@@ -369,9 +370,9 @@ TEST_F(RenameNodeTest, ReplaceWithArrayField) {
TEST_F(RenameNodeTest, CanRenameFromInvalidFieldName) {
auto update = fromjson("{$rename: {'$a': 'a'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["$a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["$a"], expCtx));
mutablebson::Document doc(fromjson("{$a: 2}"));
setPathToCreate("a");
@@ -385,9 +386,9 @@ TEST_F(RenameNodeTest, CanRenameFromInvalidFieldName) {
TEST_F(RenameNodeTest, RenameWithoutLogBuilderOrIndexData) {
auto update = fromjson("{$rename: {'a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 2}"));
setPathToCreate("b");
@@ -399,9 +400,9 @@ TEST_F(RenameNodeTest, RenameWithoutLogBuilderOrIndexData) {
TEST_F(RenameNodeTest, RenameFromNonExistentPathIsNoOp) {
auto update = fromjson("{$rename: {'a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 2}"));
setPathTaken("b");
@@ -415,9 +416,9 @@ TEST_F(RenameNodeTest, RenameFromNonExistentPathIsNoOp) {
TEST_F(RenameNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) {
auto update = fromjson("{$rename: {'a.$id': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.$id"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.$id"], expCtx));
mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}"));
setPathToCreate("b");
@@ -429,9 +430,9 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) {
TEST_F(RenameNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFalse) {
auto update = fromjson("{$rename: {'a.$id': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.$id"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.$id"], expCtx));
mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}"));
setPathToCreate("b");
@@ -451,9 +452,9 @@ TEST_F(RenameNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFa
TEST_F(RenameNodeTest, ApplyCannotRemoveImmutablePath) {
auto update = fromjson("{$rename: {'a.b': 'c'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathToCreate("c");
@@ -467,9 +468,9 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveImmutablePath) {
TEST_F(RenameNodeTest, ApplyCannotRemovePrefixOfImmutablePath) {
auto update = fromjson("{$rename: {a: 'c'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathToCreate("c");
@@ -483,9 +484,9 @@ TEST_F(RenameNodeTest, ApplyCannotRemovePrefixOfImmutablePath) {
TEST_F(RenameNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) {
auto update = fromjson("{$rename: {'a.b.c': 'd'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}"));
setPathToCreate("d");
@@ -499,9 +500,9 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) {
TEST_F(RenameNodeTest, ApplyCanRemoveImmutablePathIfNoop) {
auto update = fromjson("{$rename: {'a.b.c': 'd'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {}}}"));
setPathToCreate("d");
@@ -517,9 +518,9 @@ TEST_F(RenameNodeTest, ApplyCanRemoveImmutablePathIfNoop) {
TEST_F(RenameNodeTest, ApplyCannotCreateDollarPrefixedField) {
auto update = fromjson("{$rename: {a: '$bad'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathToCreate("$bad");
@@ -532,9 +533,9 @@ TEST_F(RenameNodeTest, ApplyCannotCreateDollarPrefixedField) {
TEST_F(RenameNodeTest, ApplyCannotOverwriteImmutablePath) {
auto update = fromjson("{$rename: {a: 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
RenameNode node;
- ASSERT_OK(node.init(update["$rename"]["a"], collator));
+ ASSERT_OK(node.init(update["$rename"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 0, b: 1}"));
setPathTaken("b");
diff --git a/src/mongo/db/update/set_node.cpp b/src/mongo/db/update/set_node.cpp
index db107e32f39..7411da5beb4 100644
--- a/src/mongo/db/update/set_node.cpp
+++ b/src/mongo/db/update/set_node.cpp
@@ -34,7 +34,7 @@
namespace mongo {
-Status SetNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status SetNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
invariant(modExpr.ok());
_val = modExpr;
diff --git a/src/mongo/db/update/set_node.h b/src/mongo/db/update/set_node.h
index 3312042f2b2..7eea1ee1cec 100644
--- a/src/mongo/db/update/set_node.h
+++ b/src/mongo/db/update/set_node.h
@@ -40,7 +40,7 @@ class SetNode : public ModifierNode {
public:
explicit SetNode(Context context = Context::kAll) : ModifierNode(context) {}
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<SetNode>(*this);
diff --git a/src/mongo/db/update/set_node_test.cpp b/src/mongo/db/update/set_node_test.cpp
index 5363c7ea654..705be2f6071 100644
--- a/src/mongo/db/update/set_node_test.cpp
+++ b/src/mongo/db/update/set_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -46,23 +47,23 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(SetNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$set: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- node.init(update["$set"].embeddedObject().firstElement(), collator).transitional_ignore();
+ node.init(update["$set"].embeddedObject().firstElement(), expCtx).transitional_ignore();
}
TEST(SetNodeTest, InitSucceedsForNonemptyElement) {
auto update = fromjson("{$set: {a: 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
}
TEST_F(SetNodeTest, ApplyNoOp) {
auto update = fromjson("{$set: {a: 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -77,9 +78,9 @@ TEST_F(SetNodeTest, ApplyNoOp) {
TEST_F(SetNodeTest, ApplyEmptyPathToCreate) {
auto update = fromjson("{$set: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -94,9 +95,9 @@ TEST_F(SetNodeTest, ApplyEmptyPathToCreate) {
TEST_F(SetNodeTest, ApplyCreatePath) {
auto update = fromjson("{$set: {'a.b.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {d: 5}}"));
setPathToCreate("b.c");
@@ -112,9 +113,9 @@ TEST_F(SetNodeTest, ApplyCreatePath) {
TEST_F(SetNodeTest, ApplyCreatePathFromRoot) {
auto update = fromjson("{$set: {'a.b': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{c: 5}"));
setPathToCreate("a.b");
@@ -129,9 +130,9 @@ TEST_F(SetNodeTest, ApplyCreatePathFromRoot) {
TEST_F(SetNodeTest, ApplyPositional) {
auto update = fromjson("{$set: {'a.$': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.$"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.$"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2]}"));
setPathTaken("a.1");
@@ -147,9 +148,9 @@ TEST_F(SetNodeTest, ApplyPositional) {
TEST_F(SetNodeTest, ApplyNonViablePathToCreate) {
auto update = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathToCreate("b");
@@ -163,9 +164,9 @@ TEST_F(SetNodeTest, ApplyNonViablePathToCreate) {
TEST_F(SetNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) {
auto update = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathToCreate("b");
@@ -182,9 +183,9 @@ TEST_F(SetNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) {
TEST_F(SetNodeTest, ApplyNoIndexDataNoLogBuilder) {
auto update = fromjson("{$set: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -198,9 +199,9 @@ TEST_F(SetNodeTest, ApplyNoIndexDataNoLogBuilder) {
TEST_F(SetNodeTest, ApplyDoesNotAffectIndexes) {
auto update = fromjson("{$set: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -214,9 +215,9 @@ TEST_F(SetNodeTest, ApplyDoesNotAffectIndexes) {
TEST_F(SetNodeTest, TypeChangeIsNotANoop) {
auto update = fromjson("{$set: {a: NumberLong(2)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: NumberInt(2)}"));
setPathTaken("a");
@@ -231,9 +232,9 @@ TEST_F(SetNodeTest, TypeChangeIsNotANoop) {
TEST_F(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) {
// Apply an op that would be a no-op.
auto update = fromjson("{$set: {a: {b : NumberInt(2)}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: { b: NumberInt(0)}}"));
// Apply a mutation to the document that will make it non-serialized.
@@ -250,9 +251,9 @@ TEST_F(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) {
TEST_F(SetNodeTest, ApplyEmptyDocument) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -266,9 +267,9 @@ TEST_F(SetNodeTest, ApplyEmptyDocument) {
TEST_F(SetNodeTest, ApplyInPlace) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -282,9 +283,9 @@ TEST_F(SetNodeTest, ApplyInPlace) {
TEST_F(SetNodeTest, ApplyOverridePath) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathTaken("a");
@@ -298,9 +299,9 @@ TEST_F(SetNodeTest, ApplyOverridePath) {
TEST_F(SetNodeTest, ApplyChangeType) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 'str'}"));
setPathTaken("a");
@@ -314,9 +315,9 @@ TEST_F(SetNodeTest, ApplyChangeType) {
TEST_F(SetNodeTest, ApplyNewPath) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 1}"));
setPathToCreate("a");
@@ -330,9 +331,9 @@ TEST_F(SetNodeTest, ApplyNewPath) {
TEST_F(SetNodeTest, ApplyLog) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -345,9 +346,9 @@ TEST_F(SetNodeTest, ApplyLog) {
TEST_F(SetNodeTest, ApplyNoOpDottedPath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a.b");
@@ -361,9 +362,9 @@ TEST_F(SetNodeTest, ApplyNoOpDottedPath) {
TEST_F(SetNodeTest, TypeChangeOnDottedPathIsNotANoOp) {
auto update = fromjson("{$set: {'a.b': NumberInt(2)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: NumberLong(2)}}"));
setPathTaken("a.b");
@@ -377,9 +378,9 @@ TEST_F(SetNodeTest, TypeChangeOnDottedPathIsNotANoOp) {
TEST_F(SetNodeTest, ApplyPathNotViable) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a:1}"));
setPathToCreate("b");
@@ -392,9 +393,9 @@ TEST_F(SetNodeTest, ApplyPathNotViable) {
TEST_F(SetNodeTest, ApplyPathNotViableArrray) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a:[{b:1}]}"));
setPathToCreate("b");
@@ -407,9 +408,9 @@ TEST_F(SetNodeTest, ApplyPathNotViableArrray) {
TEST_F(SetNodeTest, ApplyInPlaceDottedPath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathTaken("a.b");
@@ -423,9 +424,9 @@ TEST_F(SetNodeTest, ApplyInPlaceDottedPath) {
TEST_F(SetNodeTest, ApplyChangeTypeDottedPath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 'str'}}"));
setPathTaken("a.b");
@@ -439,9 +440,9 @@ TEST_F(SetNodeTest, ApplyChangeTypeDottedPath) {
TEST_F(SetNodeTest, ApplyChangePath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}"));
setPathTaken("a.b");
@@ -455,9 +456,9 @@ TEST_F(SetNodeTest, ApplyChangePath) {
TEST_F(SetNodeTest, ApplyExtendPath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {c: 1}}"));
setPathToCreate("b");
@@ -472,9 +473,9 @@ TEST_F(SetNodeTest, ApplyExtendPath) {
TEST_F(SetNodeTest, ApplyNewDottedPath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{c: 1}"));
setPathToCreate("a.b");
@@ -488,9 +489,9 @@ TEST_F(SetNodeTest, ApplyNewDottedPath) {
TEST_F(SetNodeTest, ApplyEmptyDoc) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a.b");
@@ -504,9 +505,9 @@ TEST_F(SetNodeTest, ApplyEmptyDoc) {
TEST_F(SetNodeTest, ApplyFieldWithDot) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{'a.b':4}"));
setPathToCreate("a.b");
@@ -520,9 +521,9 @@ TEST_F(SetNodeTest, ApplyFieldWithDot) {
TEST_F(SetNodeTest, ApplyNoOpArrayIndex) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"));
setPathTaken("a.2.b");
@@ -536,9 +537,9 @@ TEST_F(SetNodeTest, ApplyNoOpArrayIndex) {
TEST_F(SetNodeTest, TypeChangeInArrayIsNotANoOp) {
auto update = fromjson("{$set: {'a.2.b': NumberInt(2)}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2.0}]}"));
setPathTaken("a.2.b");
@@ -552,9 +553,9 @@ TEST_F(SetNodeTest, TypeChangeInArrayIsNotANoOp) {
TEST_F(SetNodeTest, ApplyNonViablePath) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 0}"));
setPathToCreate("2.b");
@@ -567,9 +568,9 @@ TEST_F(SetNodeTest, ApplyNonViablePath) {
TEST_F(SetNodeTest, ApplyInPlaceArrayIndex) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}"));
setPathTaken("a.2.b");
@@ -583,9 +584,9 @@ TEST_F(SetNodeTest, ApplyInPlaceArrayIndex) {
TEST_F(SetNodeTest, ApplyNormalArray) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1}]}"));
setPathToCreate("2.b");
@@ -600,9 +601,9 @@ TEST_F(SetNodeTest, ApplyNormalArray) {
TEST_F(SetNodeTest, ApplyPaddingArray) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 0}]}"));
setPathToCreate("2.b");
@@ -617,9 +618,9 @@ TEST_F(SetNodeTest, ApplyPaddingArray) {
TEST_F(SetNodeTest, ApplyNumericObject) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 0}}"));
setPathToCreate("2.b");
@@ -634,9 +635,9 @@ TEST_F(SetNodeTest, ApplyNumericObject) {
TEST_F(SetNodeTest, ApplyNumericField) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {'2': {b: 1}}}"));
setPathTaken("a.2.b");
@@ -650,9 +651,9 @@ TEST_F(SetNodeTest, ApplyNumericField) {
TEST_F(SetNodeTest, ApplyExtendNumericField) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {'2': {c: 1}}}"));
setPathToCreate("b");
@@ -667,9 +668,9 @@ TEST_F(SetNodeTest, ApplyExtendNumericField) {
TEST_F(SetNodeTest, ApplyEmptyObject) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {}}"));
setPathToCreate("2.b");
@@ -684,9 +685,9 @@ TEST_F(SetNodeTest, ApplyEmptyObject) {
TEST_F(SetNodeTest, ApplyEmptyArray) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathToCreate("2.b");
@@ -701,9 +702,9 @@ TEST_F(SetNodeTest, ApplyEmptyArray) {
TEST_F(SetNodeTest, ApplyLogDottedPath) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b:0}, {b:1}]}"));
setPathToCreate("2.b");
@@ -717,9 +718,9 @@ TEST_F(SetNodeTest, ApplyLogDottedPath) {
TEST_F(SetNodeTest, LogEmptyArray) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: []}"));
setPathToCreate("2.b");
@@ -733,9 +734,9 @@ TEST_F(SetNodeTest, LogEmptyArray) {
TEST_F(SetNodeTest, LogEmptyObject) {
auto update = fromjson("{$set: {'a.2.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.2.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.2.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {}}"));
setPathToCreate("2.b");
@@ -749,9 +750,9 @@ TEST_F(SetNodeTest, LogEmptyObject) {
TEST_F(SetNodeTest, ApplyNoOpComplex) {
auto update = fromjson("{$set: {'a.1.b': {c: 1, d: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}"));
setPathTaken("a.1.b");
@@ -765,9 +766,9 @@ TEST_F(SetNodeTest, ApplyNoOpComplex) {
TEST_F(SetNodeTest, ApplySameStructure) {
auto update = fromjson("{$set: {'a.1.b': {c: 1, d: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, xxx: 1}}]}}"));
setPathTaken("a.1.b");
@@ -781,9 +782,9 @@ TEST_F(SetNodeTest, ApplySameStructure) {
TEST_F(SetNodeTest, NonViablePathWithoutRepl) {
auto update = fromjson("{$set: {'a.1.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathToCreate("1.b");
@@ -796,9 +797,9 @@ TEST_F(SetNodeTest, NonViablePathWithoutRepl) {
TEST_F(SetNodeTest, SingleFieldFromReplication) {
auto update = fromjson("{$set: {'a.1.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{_id:1, a: 1}"));
setPathToCreate("1.b");
@@ -814,9 +815,9 @@ TEST_F(SetNodeTest, SingleFieldFromReplication) {
TEST_F(SetNodeTest, SingleFieldNoIdFromReplication) {
auto update = fromjson("{$set: {'a.1.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathToCreate("1.b");
@@ -832,9 +833,9 @@ TEST_F(SetNodeTest, SingleFieldNoIdFromReplication) {
TEST_F(SetNodeTest, NestedFieldFromReplication) {
auto update = fromjson("{$set: {'a.a.1.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{_id:1, a: {a: 1}}"));
setPathToCreate("1.b");
@@ -850,9 +851,9 @@ TEST_F(SetNodeTest, NestedFieldFromReplication) {
TEST_F(SetNodeTest, DoubleNestedFieldFromReplication) {
auto update = fromjson("{$set: {'a.b.c.d': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c.d"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c.d"], expCtx));
mutablebson::Document doc(fromjson("{_id:1, a: {b: {c: 1}}}"));
setPathToCreate("d");
@@ -868,9 +869,9 @@ TEST_F(SetNodeTest, DoubleNestedFieldFromReplication) {
TEST_F(SetNodeTest, NestedFieldNoIdFromReplication) {
auto update = fromjson("{$set: {'a.a.1.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.a.1.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {a: 1}}"));
setPathToCreate("1.b");
@@ -886,9 +887,9 @@ TEST_F(SetNodeTest, NestedFieldNoIdFromReplication) {
TEST_F(SetNodeTest, ReplayArrayFieldNotAppendedIntermediateFromReplication) {
auto update = fromjson("{$set: {'a.0.b': [0,2]}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.0.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.0.b"], expCtx));
mutablebson::Document doc(fromjson("{_id: 0, a: [1, {b: [1]}]}"));
setPathToCreate("b");
@@ -904,9 +905,9 @@ TEST_F(SetNodeTest, ReplayArrayFieldNotAppendedIntermediateFromReplication) {
TEST_F(SetNodeTest, Set6) {
auto update = fromjson("{$set: {'r.a': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["r.a"], collator));
+ ASSERT_OK(node.init(update["$set"]["r.a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 1, r: {a:1, b:2}}"));
setPathTaken("r.a");
@@ -922,9 +923,9 @@ TEST_F(SetNodeTest, Set6) {
TEST_F(SetNodeTest, Set6FromRepl) {
auto update = fromjson("{$set: { 'r.a': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["r.a"], collator));
+ ASSERT_OK(node.init(update["$set"]["r.a"], expCtx));
mutablebson::Document doc(fromjson("{_id: 1, r: {a:1, b:2}}"));
setPathTaken("r.a");
@@ -944,9 +945,9 @@ TEST_F(SetNodeTest, ApplySetModToEphemeralDocument) {
// latent debug only defect in mutable BSON, so this is more a test of mutable than
// $set.
auto update = fromjson("{ $set: { x: { a: 100, b: 2 }}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["x"], collator));
+ ASSERT_OK(node.init(update["$set"]["x"], expCtx));
mutablebson::Document doc;
Element x = doc.makeElementObject("x");
@@ -965,9 +966,9 @@ TEST_F(SetNodeTest, ApplySetModToEphemeralDocument) {
TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInsideSetElement) {
auto update = fromjson("{$set: {a: {$bad: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -980,9 +981,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInsideSetElement) {
TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtStartOfPath) {
auto update = fromjson("{$set: {'$bad.a': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["$bad.a"], collator));
+ ASSERT_OK(node.init(update["$set"]["$bad.a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("$bad.a");
@@ -995,9 +996,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtStartOfPath) {
TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInMiddleOfPath) {
auto update = fromjson("{$set: {'a.$bad.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.$bad.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.$bad.b"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a.$bad.b");
@@ -1010,9 +1011,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInMiddleOfPath) {
TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtEndOfPath) {
auto update = fromjson("{$set: {'a.$bad': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.$bad"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.$bad"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a.$bad");
@@ -1025,9 +1026,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtEndOfPath) {
TEST_F(SetNodeTest, ApplyCanCreateDollarPrefixedFieldNameWhenValidateForStorageIsFalse) {
auto update = fromjson("{$set: {$bad: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["$bad"], collator));
+ ASSERT_OK(node.init(update["$set"]["$bad"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("$bad");
@@ -1044,9 +1045,9 @@ TEST_F(SetNodeTest, ApplyCanCreateDollarPrefixedFieldNameWhenValidateForStorageI
TEST_F(SetNodeTest, ApplyCannotOverwriteImmutablePath) {
auto update = fromjson("{$set: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a.b");
@@ -1060,9 +1061,9 @@ TEST_F(SetNodeTest, ApplyCannotOverwriteImmutablePath) {
TEST_F(SetNodeTest, ApplyCanPerformNoopOnImmutablePath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a.b");
@@ -1079,9 +1080,9 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnImmutablePath) {
TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToRemoveImmutablePath) {
auto update = fromjson("{$set: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -1095,9 +1096,9 @@ TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToRemoveImmutablePath) {
TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToModifyImmutablePath) {
auto update = fromjson("{$set: {a: {b: 1}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -1111,9 +1112,9 @@ TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToModifyImmutablePath) {
TEST_F(SetNodeTest, ApplyCanPerformNoopOnPrefixOfImmutablePath) {
auto update = fromjson("{$set: {a: {b: 2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -1130,9 +1131,9 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnPrefixOfImmutablePath) {
TEST_F(SetNodeTest, ApplyCanOverwritePrefixToCreateImmutablePath) {
auto update = fromjson("{$set: {a: {b: 2}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
@@ -1149,9 +1150,9 @@ TEST_F(SetNodeTest, ApplyCanOverwritePrefixToCreateImmutablePath) {
TEST_F(SetNodeTest, ApplyCanOverwritePrefixOfImmutablePathIfNoopOnImmutablePath) {
auto update = fromjson("{$set: {a: {b: 2, c: 3}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 2}}"));
setPathTaken("a");
@@ -1168,9 +1169,9 @@ TEST_F(SetNodeTest, ApplyCanOverwritePrefixOfImmutablePathIfNoopOnImmutablePath)
TEST_F(SetNodeTest, ApplyCannotOverwriteSuffixOfImmutablePath) {
auto update = fromjson("{$set: {'a.b.c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 2}}}"));
setPathTaken("a.b.c");
@@ -1184,9 +1185,9 @@ TEST_F(SetNodeTest, ApplyCannotOverwriteSuffixOfImmutablePath) {
TEST_F(SetNodeTest, ApplyCanPerformNoopOnSuffixOfImmutablePath) {
auto update = fromjson("{$set: {'a.b.c': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 2}}}"));
setPathTaken("a.b.c");
@@ -1203,9 +1204,9 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnSuffixOfImmutablePath) {
TEST_F(SetNodeTest, ApplyCannotCreateFieldAtEndOfImmutablePath) {
auto update = fromjson("{$set: {'a.b.c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {}}}"));
setPathToCreate("c");
@@ -1220,9 +1221,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateFieldAtEndOfImmutablePath) {
TEST_F(SetNodeTest, ApplyCannotCreateFieldBeyondEndOfImmutablePath) {
auto update = fromjson("{$set: {'a.b.c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {}}}"));
setPathToCreate("c");
@@ -1237,9 +1238,9 @@ TEST_F(SetNodeTest, ApplyCannotCreateFieldBeyondEndOfImmutablePath) {
TEST_F(SetNodeTest, ApplyCanCreateImmutablePath) {
auto update = fromjson("{$set: {'a.b': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$set"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {}}"));
setPathToCreate("b");
@@ -1257,9 +1258,9 @@ TEST_F(SetNodeTest, ApplyCanCreateImmutablePath) {
TEST_F(SetNodeTest, ApplyCanCreatePrefixOfImmutablePath) {
auto update = fromjson("{$set: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node;
- ASSERT_OK(node.init(update["$set"]["a"], collator));
+ ASSERT_OK(node.init(update["$set"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -1276,9 +1277,9 @@ TEST_F(SetNodeTest, ApplyCanCreatePrefixOfImmutablePath) {
TEST_F(SetNodeTest, ApplySetOnInsertIsNoopWhenInsertIsFalse) {
auto update = fromjson("{$setOnInsert: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node(UpdateNode::Context::kInsertOnly);
- ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator));
+ ASSERT_OK(node.init(update["$setOnInsert"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -1293,9 +1294,9 @@ TEST_F(SetNodeTest, ApplySetOnInsertIsNoopWhenInsertIsFalse) {
TEST_F(SetNodeTest, ApplySetOnInsertIsAppliedWhenInsertIsTrue) {
auto update = fromjson("{$setOnInsert: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node(UpdateNode::Context::kInsertOnly);
- ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator));
+ ASSERT_OK(node.init(update["$setOnInsert"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -1311,9 +1312,9 @@ TEST_F(SetNodeTest, ApplySetOnInsertIsAppliedWhenInsertIsTrue) {
TEST_F(SetNodeTest, ApplySetOnInsertExistingPath) {
auto update = fromjson("{$setOnInsert: {a: 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
SetNode node(UpdateNode::Context::kInsertOnly);
- ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator));
+ ASSERT_OK(node.init(update["$setOnInsert"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 1}"));
setPathTaken("a");
diff --git a/src/mongo/db/update/unset_node.cpp b/src/mongo/db/update/unset_node.cpp
index 5ff55a0bf64..9c07e1ea0b0 100644
--- a/src/mongo/db/update/unset_node.cpp
+++ b/src/mongo/db/update/unset_node.cpp
@@ -34,7 +34,7 @@
namespace mongo {
-Status UnsetNode::init(BSONElement modExpr, const CollatorInterface* collator) {
+Status UnsetNode::init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
// Note that we don't need to store modExpr, because $unset does not do anything with its value.
invariant(modExpr.ok());
return Status::OK();
diff --git a/src/mongo/db/update/unset_node.h b/src/mongo/db/update/unset_node.h
index 645497ef6a9..93fa314ad33 100644
--- a/src/mongo/db/update/unset_node.h
+++ b/src/mongo/db/update/unset_node.h
@@ -38,7 +38,7 @@ namespace mongo {
*/
class UnsetNode : public ModifierNode {
public:
- Status init(BSONElement modExpr, const CollatorInterface* collator) final;
+ Status init(BSONElement modExpr, const boost::intrusive_ptr<ExpressionContext>& expCtx) final;
std::unique_ptr<UpdateNode> clone() const final {
return stdx::make_unique<UnsetNode>(*this);
diff --git a/src/mongo/db/update/unset_node_test.cpp b/src/mongo/db/update/unset_node_test.cpp
index 26c89e05048..1c68c8520dd 100644
--- a/src/mongo/db/update/unset_node_test.cpp
+++ b/src/mongo/db/update/unset_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
@@ -46,16 +47,16 @@ using mongo::mutablebson::countChildren;
DEATH_TEST(UnsetNodeTest, InitFailsForEmptyElement, "Invariant failure modExpr.ok()") {
auto update = fromjson("{$unset: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- node.init(update["$unset"].embeddedObject().firstElement(), collator).transitional_ignore();
+ node.init(update["$unset"].embeddedObject().firstElement(), expCtx).transitional_ignore();
}
DEATH_TEST_F(UnsetNodeTest, ApplyToRootFails, "Invariant failure !applyParams.pathTaken->empty()") {
auto update = fromjson("{$unset: {}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"], collator));
+ ASSERT_OK(node.init(update["$unset"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
node.apply(getApplyParams(doc.root()));
@@ -63,17 +64,17 @@ DEATH_TEST_F(UnsetNodeTest, ApplyToRootFails, "Invariant failure !applyParams.pa
TEST(UnsetNodeTest, InitSucceedsForNonemptyElement) {
auto update = fromjson("{$unset: {a: 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
}
/* This is a no-op because we are unsetting a field that does not exit. */
TEST_F(UnsetNodeTest, UnsetNoOp) {
auto update = fromjson("{$unset: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{b: 5}"));
setPathToCreate("a");
@@ -88,9 +89,9 @@ TEST_F(UnsetNodeTest, UnsetNoOp) {
TEST_F(UnsetNodeTest, UnsetNoOpDottedPath) {
auto update = fromjson("{$unset: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathToCreate("b");
@@ -106,9 +107,9 @@ TEST_F(UnsetNodeTest, UnsetNoOpDottedPath) {
TEST_F(UnsetNodeTest, UnsetNoOpThroughArray) {
auto update = fromjson("{$unset: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a:[{b:1}]}"));
setPathToCreate("b");
@@ -124,9 +125,9 @@ TEST_F(UnsetNodeTest, UnsetNoOpThroughArray) {
TEST_F(UnsetNodeTest, UnsetNoOpEmptyDoc) {
auto update = fromjson("{$unset: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{}"));
setPathToCreate("a");
@@ -141,9 +142,9 @@ TEST_F(UnsetNodeTest, UnsetNoOpEmptyDoc) {
TEST_F(UnsetNodeTest, UnsetTopLevelPath) {
auto update = fromjson("{$unset: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -158,9 +159,9 @@ TEST_F(UnsetNodeTest, UnsetTopLevelPath) {
TEST_F(UnsetNodeTest, UnsetNestedPath) {
auto update = fromjson("{$unset: {'a.b.c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 6}}}}"));
setPathTaken("a.b.c");
@@ -175,9 +176,9 @@ TEST_F(UnsetNodeTest, UnsetNestedPath) {
TEST_F(UnsetNodeTest, UnsetObject) {
auto update = fromjson("{$unset: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 6}}}}"));
setPathTaken("a.b");
@@ -192,9 +193,9 @@ TEST_F(UnsetNodeTest, UnsetObject) {
TEST_F(UnsetNodeTest, UnsetArrayElement) {
auto update = fromjson("{$unset: {'a.0': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.0"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.0"], expCtx));
mutablebson::Document doc(fromjson("{a:[1], b:1}"));
setPathTaken("a.0");
@@ -209,9 +210,9 @@ TEST_F(UnsetNodeTest, UnsetArrayElement) {
TEST_F(UnsetNodeTest, UnsetPositional) {
auto update = fromjson("{$unset: {'a.$': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.$"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.$"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2]}"));
setPathTaken("a.1");
@@ -227,9 +228,9 @@ TEST_F(UnsetNodeTest, UnsetPositional) {
TEST_F(UnsetNodeTest, UnsetEntireArray) {
auto update = fromjson("{$unset: {'a': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: [0, 1, 2]}"));
setPathTaken("a");
@@ -244,9 +245,9 @@ TEST_F(UnsetNodeTest, UnsetEntireArray) {
TEST_F(UnsetNodeTest, UnsetFromObjectInArray) {
auto update = fromjson("{$unset: {'a.0.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.0.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.0.b"], expCtx));
mutablebson::Document doc(fromjson("{a: [{b: 1}]}"));
setPathTaken("a.0.b");
@@ -261,9 +262,9 @@ TEST_F(UnsetNodeTest, UnsetFromObjectInArray) {
TEST_F(UnsetNodeTest, CanUnsetInvalidField) {
auto update = fromjson("{$unset: {'a.$.$b': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.$.$b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.$.$b"], expCtx));
mutablebson::Document doc(fromjson("{b: 1, a: [{$b: 1}]}"));
setPathTaken("a.0.$b");
@@ -278,9 +279,9 @@ TEST_F(UnsetNodeTest, CanUnsetInvalidField) {
TEST_F(UnsetNodeTest, ApplyNoIndexDataNoLogBuilder) {
auto update = fromjson("{$unset: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -294,9 +295,9 @@ TEST_F(UnsetNodeTest, ApplyNoIndexDataNoLogBuilder) {
TEST_F(UnsetNodeTest, ApplyDoesNotAffectIndexes) {
auto update = fromjson("{$unset: {a: 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: 5}"));
setPathTaken("a");
@@ -311,9 +312,9 @@ TEST_F(UnsetNodeTest, ApplyDoesNotAffectIndexes) {
TEST_F(UnsetNodeTest, ApplyFieldWithDot) {
auto update = fromjson("{$unset: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{'a.b':4, a: {b: 2}}"));
setPathTaken("a.b");
@@ -328,9 +329,9 @@ TEST_F(UnsetNodeTest, ApplyFieldWithDot) {
TEST_F(UnsetNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) {
auto update = fromjson("{$unset: {'a.$id': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.$id"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.$id"], expCtx));
mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}"));
setPathTaken("a.$id");
@@ -342,9 +343,9 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) {
TEST_F(UnsetNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFalse) {
auto update = fromjson("{$unset: {'a.$id': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.$id"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.$id"], expCtx));
mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}"));
setPathTaken("a.$id");
@@ -362,9 +363,9 @@ TEST_F(UnsetNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFal
TEST_F(UnsetNodeTest, ApplyCannotRemoveImmutablePath) {
auto update = fromjson("{$unset: {'a.b': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathTaken("a.b");
@@ -378,9 +379,9 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveImmutablePath) {
TEST_F(UnsetNodeTest, ApplyCannotRemovePrefixOfImmutablePath) {
auto update = fromjson("{$unset: {a: true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathTaken("a");
@@ -394,9 +395,9 @@ TEST_F(UnsetNodeTest, ApplyCannotRemovePrefixOfImmutablePath) {
TEST_F(UnsetNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) {
auto update = fromjson("{$unset: {'a.b.c': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}"));
setPathTaken("a.b.c");
@@ -410,9 +411,9 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) {
TEST_F(UnsetNodeTest, ApplyCanRemoveImmutablePathIfNoop) {
auto update = fromjson("{$unset: {'a.b.c': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UnsetNode node;
- ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator));
+ ASSERT_OK(node.init(update["$unset"]["a.b.c"], expCtx));
mutablebson::Document doc(fromjson("{a: {b: 1}}"));
setPathToCreate("c");
diff --git a/src/mongo/db/update/update_array_node_test.cpp b/src/mongo/db/update/update_array_node_test.cpp
index cd573a7dc80..38004cd39f9 100644
--- a/src/mongo/db/update/update_array_node_test.cpp
+++ b/src/mongo/db/update/update_array_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/update/update_node_test_fixture.h"
#include "mongo/db/update/update_object_node.h"
#include "mongo/unittest/death_test.h"
@@ -47,15 +48,15 @@ using mongo::mutablebson::Element;
TEST_F(UpdateArrayNodeTest, ApplyCreatePathFails) {
auto update = fromjson("{$set: {'a.b.$[i]': 0}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -71,15 +72,15 @@ TEST_F(UpdateArrayNodeTest, ApplyCreatePathFails) {
TEST_F(UpdateArrayNodeTest, ApplyToNonArrayFails) {
auto update = fromjson("{$set: {'a.$[i]': 0}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -94,15 +95,15 @@ TEST_F(UpdateArrayNodeTest, ApplyToNonArrayFails) {
TEST_F(UpdateArrayNodeTest, UpdateIsAppliedToAllMatchingElements) {
auto update = fromjson("{$set: {'a.$[i]': 2}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -121,15 +122,15 @@ DEATH_TEST_F(UpdateArrayNodeTest,
"Invariant failure childElement.hasValue()") {
auto update = fromjson("{$set: {'a.$[i].b': 0}}");
auto arrayFilter = fromjson("{'i.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -142,14 +143,14 @@ DEATH_TEST_F(UpdateArrayNodeTest,
TEST_F(UpdateArrayNodeTest, UpdateForEmptyIdentifierIsAppliedToAllArrayElements) {
auto update = fromjson("{$set: {'a.$[]': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -168,29 +169,29 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElement) {
auto arrayFilterI = fromjson("{'i.b': 0}");
auto arrayFilterJ = fromjson("{'j.c': 0}");
auto arrayFilterK = fromjson("{'k.d': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
- arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
+ arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[k].d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -208,22 +209,22 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsUsingMergedChildr
auto update = fromjson("{$set: {'a.$[i].b': 1, 'a.$[j].c': 1}}");
auto arrayFilterI = fromjson("{'i.b': 0}");
auto arrayFilterJ = fromjson("{'j.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -242,29 +243,29 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsWithoutMergedChil
auto arrayFilterI = fromjson("{'i.b': 0}");
auto arrayFilterJ = fromjson("{'j.c': 0}");
auto arrayFilterK = fromjson("{'k.d': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
- arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
+ arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[k].d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -280,20 +281,20 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsWithoutMergedChil
TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementWithEmptyIdentifiers) {
auto update = fromjson("{$set: {'a.$[].b': 1, 'a.$[].c': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -313,24 +314,24 @@ TEST_F(UpdateArrayNodeTest, ApplyNestedArrayUpdates) {
auto arrayFilterJ = fromjson("{'j.c': 0}");
auto arrayFilterK = fromjson("{'k.x': 0}");
auto arrayFilterL = fromjson("{'l.d': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
- arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, collator));
- arrayFilters["l"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterL, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
+ arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, expCtx));
+ arrayFilters["l"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterL, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b.$[j].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[k].b.$[l].d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -348,22 +349,22 @@ TEST_F(UpdateArrayNodeTest, ApplyUpdatesWithMergeConflictToArrayElementFails) {
auto update = fromjson("{$set: {'a.$[i]': 1, 'a.$[j]': 1}}");
auto arrayFilterI = fromjson("{'i': 0}");
auto arrayFilterJ = fromjson("{'j': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -379,22 +380,22 @@ TEST_F(UpdateArrayNodeTest, ApplyUpdatesWithEmptyIdentifiersWithMergeConflictToA
auto update = fromjson("{$set: {'a.$[].b.$[i]': 1, 'a.$[].b.$[j]': 1}}");
auto arrayFilterI = fromjson("{'i': 0}");
auto arrayFilterJ = fromjson("{'j': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[].b.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[].b.$[j]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -412,24 +413,24 @@ TEST_F(UpdateArrayNodeTest, ApplyNestedArrayUpdatesWithMergeConflictFails) {
auto arrayFilterJ = fromjson("{j: 0}");
auto arrayFilterK = fromjson("{'k.c': 0}");
auto arrayFilterL = fromjson("{l: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
- arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, collator));
- arrayFilters["l"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterL, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
+ arrayFilters["k"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterK, expCtx));
+ arrayFilters["l"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterL, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b.$[j]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[k].b.$[l]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -444,15 +445,15 @@ TEST_F(UpdateArrayNodeTest, ApplyNestedArrayUpdatesWithMergeConflictFails) {
TEST_F(UpdateArrayNodeTest, NoArrayElementsMatch) {
auto update = fromjson("{$set: {'a.$[i]': 1}}");
auto arrayFilter = fromjson("{'i': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -469,15 +470,15 @@ TEST_F(UpdateArrayNodeTest, NoArrayElementsMatch) {
TEST_F(UpdateArrayNodeTest, UpdatesToAllArrayElementsAreNoops) {
auto update = fromjson("{$set: {'a.$[i]': 1}}");
auto arrayFilter = fromjson("{'i': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -494,15 +495,15 @@ TEST_F(UpdateArrayNodeTest, UpdatesToAllArrayElementsAreNoops) {
TEST_F(UpdateArrayNodeTest, NoArrayElementAffectsIndexes) {
auto update = fromjson("{$set: {'a.$[i].b': 0}}");
auto arrayFilter = fromjson("{'i.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -519,15 +520,15 @@ TEST_F(UpdateArrayNodeTest, NoArrayElementAffectsIndexes) {
TEST_F(UpdateArrayNodeTest, WhenOneElementIsMatchedLogElementUpdateDirectly) {
auto update = fromjson("{$set: {'a.$[i].b': 0}}");
auto arrayFilter = fromjson("{'i.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -544,15 +545,15 @@ TEST_F(UpdateArrayNodeTest, WhenOneElementIsMatchedLogElementUpdateDirectly) {
TEST_F(UpdateArrayNodeTest, WhenOneElementIsModifiedLogElement) {
auto update = fromjson("{$set: {'a.$[i].b': 0}}");
auto arrayFilter = fromjson("{'i.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -568,14 +569,14 @@ TEST_F(UpdateArrayNodeTest, WhenOneElementIsModifiedLogElement) {
TEST_F(UpdateArrayNodeTest, ArrayUpdateOnEmptyArrayIsANoop) {
auto update = fromjson("{$set: {'a.$[]': 0}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -592,15 +593,15 @@ TEST_F(UpdateArrayNodeTest, ArrayUpdateOnEmptyArrayIsANoop) {
TEST_F(UpdateArrayNodeTest, ApplyPositionalInsideArrayUpdate) {
auto update = fromjson("{$set: {'a.$[i].b.$': 1}}");
auto arrayFilter = fromjson("{'i.c': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -618,15 +619,15 @@ TEST_F(UpdateArrayNodeTest, ApplyPositionalInsideArrayUpdate) {
TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateFromReplication) {
auto update = fromjson("{$set: {'a.$[i].b': 1}}");
auto arrayFilter = fromjson("{'i': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -644,15 +645,15 @@ TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateFromReplication) {
TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateNotFromReplication) {
auto update = fromjson("{$set: {'a.$[i].b': 1}}");
auto arrayFilter = fromjson("{'i': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -667,15 +668,15 @@ TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateNotFromReplication) {
TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateWithoutLogBuilderOrIndexData) {
auto update = fromjson("{$set: {'a.$[i]': 1}}");
auto arrayFilter = fromjson("{'i': 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp
index cfcc2d891fd..7eb4f4ffd7c 100644
--- a/src/mongo/db/update/update_driver.cpp
+++ b/src/mongo/db/update/update_driver.cpp
@@ -107,7 +107,7 @@ modifiertable::ModifierType validateMod(BSONElement mod) {
bool parseUpdateExpression(
BSONObj updateExpr,
UpdateObjectNode* root,
- const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters) {
bool positional = false;
std::set<std::string> foundIdentifiers;
@@ -127,7 +127,7 @@ bool parseUpdateExpression(
auto modType = validateMod(mod);
for (auto&& field : mod.Obj()) {
auto statusWithPositional = UpdateObjectNode::parseAndMerge(
- root, modType, field, collator, arrayFilters, foundIdentifiers);
+ root, modType, field, expCtx, arrayFilters, foundIdentifiers);
uassertStatusOK(statusWithPositional);
positional = positional || statusWithPositional.getValue();
}
@@ -239,7 +239,7 @@ Status UpdateDriver::parse(
case UpdateSemantics::kUpdateNode: {
auto root = stdx::make_unique<UpdateObjectNode>();
_positional =
- parseUpdateExpression(updateExpr, root.get(), _modOptions.collator, arrayFilters);
+ parseUpdateExpression(updateExpr, root.get(), _modOptions.expCtx, arrayFilters);
_root = std::move(root);
break;
}
@@ -555,7 +555,7 @@ void UpdateDriver::setCollator(const CollatorInterface* collator) {
mod->setCollator(collator);
}
- _modOptions.collator = collator;
+ _modOptions.expCtx->setCollator(collator);
}
void UpdateDriver::clear() {
diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h
index 3a74b1ca753..337a1abfe87 100644
--- a/src/mongo/db/update/update_driver.h
+++ b/src/mongo/db/update/update_driver.h
@@ -218,7 +218,8 @@ struct UpdateDriver::Options {
bool logOp;
ModifierInterface::Options modOptions;
- Options() : logOp(false), modOptions() {}
+ explicit Options(const boost::intrusive_ptr<ExpressionContext>& expCtx)
+ : logOp(false), modOptions(ModifierInterface::Options::normal(expCtx)) {}
};
} // namespace mongo
diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp
index 52a4baa8b9a..f64c1e353d3 100644
--- a/src/mongo/db/update/update_driver_test.cpp
+++ b/src/mongo/db/update/update_driver_test.cpp
@@ -39,6 +39,7 @@
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/query_test_service_context.h"
#include "mongo/db/update_index_data.h"
@@ -50,7 +51,8 @@ namespace {
using mongoutils::str::stream;
TEST(Parse, Normal) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_OK(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters));
@@ -59,7 +61,8 @@ TEST(Parse, Normal) {
}
TEST(Parse, MultiMods) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_OK(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters));
@@ -68,7 +71,8 @@ TEST(Parse, MultiMods) {
}
TEST(Parse, MixingMods) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_OK(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters));
@@ -77,7 +81,8 @@ TEST(Parse, MixingMods) {
}
TEST(Parse, ObjectReplacment) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_OK(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters));
@@ -85,7 +90,8 @@ TEST(Parse, ObjectReplacment) {
}
TEST(Parse, EmptyMod) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
@@ -96,7 +102,8 @@ TEST(Parse, EmptyMod) {
}
TEST(Parse, WrongMod) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
@@ -107,7 +114,8 @@ TEST(Parse, WrongMod) {
}
TEST(Parse, WrongType) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
@@ -119,7 +127,8 @@ TEST(Parse, WrongType) {
}
TEST(Parse, ModsWithLaterObjReplacement) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
@@ -131,7 +140,8 @@ TEST(Parse, ModsWithLaterObjReplacement) {
}
TEST(Parse, SetOnInsert) {
- UpdateDriver::Options opts;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_OK(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters));
@@ -140,9 +150,10 @@ TEST(Parse, SetOnInsert) {
}
TEST(Collator, SetCollationUpdatesModifierInterfaces) {
- CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ CollatorInterfaceMock reverseStringCollator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj updateDocument = fromjson("{$max: {a: 'abd'}}");
- UpdateDriver::Options opts;
+ UpdateDriver::Options opts(expCtx);
UpdateDriver driver(opts);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
@@ -154,7 +165,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) {
const FieldRefSet emptyImmutablePaths;
bool modified = false;
mutablebson::Document doc(fromjson("{a: 'cba'}"));
- driver.setCollator(&collator);
+ driver.setCollator(&reverseStringCollator);
driver
.update(StringData(),
original,
@@ -178,11 +189,13 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) {
class CreateFromQueryFixture : public mongo::unittest::Test {
public:
CreateFromQueryFixture()
- : _driverOps(new UpdateDriver(UpdateDriver::Options())),
- _driverRepl(new UpdateDriver(UpdateDriver::Options())) {
+ : _opCtx(_serviceContext.makeOperationContext()),
+ _driverOps(new UpdateDriver(
+ UpdateDriver::Options(new ExpressionContext(_opCtx.get(), nullptr)))),
+ _driverRepl(new UpdateDriver(
+ UpdateDriver::Options(new ExpressionContext(_opCtx.get(), nullptr)))) {
_driverOps->parse(fromjson("{$set:{'_':1}}"), _arrayFilters).transitional_ignore();
_driverRepl->parse(fromjson("{}"), _arrayFilters).transitional_ignore();
- _opCtx = _serviceContext.makeOperationContext();
}
mutablebson::Document& doc() {
diff --git a/src/mongo/db/update/update_leaf_node.h b/src/mongo/db/update/update_leaf_node.h
index c268facec30..9a7c53dede9 100644
--- a/src/mongo/db/update/update_leaf_node.h
+++ b/src/mongo/db/update/update_leaf_node.h
@@ -28,6 +28,7 @@
#pragma once
+#include "mongo/db/pipeline/expression_context.h"
#include "mongo/db/update/update_node.h"
namespace mongo {
@@ -47,11 +48,12 @@ public:
* root["$set"]["a.b"]. Returns a non-OK status if the value in 'modExpr' is invalid for the
* type of leaf node. 'modExpr' must not be empty.
*
- * Some leaf nodes require a collator during initialization. For example, $pull requires a
- * collator to construct a MatchExpression that will be used for applying updates across
- * multiple documents.
+ * Some leaf nodes require an ExpressionContext during initialization. For example, $pull
+ * requires an ExpressionContext to construct a MatchExpression that will be used for applying
+ * updates across multiple documents.
*/
- virtual Status init(BSONElement modExpr, const CollatorInterface* collator) = 0;
+ virtual Status init(BSONElement modExpr,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) = 0;
/* Check if it would be possible to create the path at 'pathToCreate' but don't actually create
* it. If 'element' is not an embedded object or array (e.g., we are trying to create path
diff --git a/src/mongo/db/update/update_object_node.cpp b/src/mongo/db/update/update_object_node.cpp
index 9b984eb3a33..542ed8cd201 100644
--- a/src/mongo/db/update/update_object_node.cpp
+++ b/src/mongo/db/update/update_object_node.cpp
@@ -179,7 +179,7 @@ StatusWith<bool> UpdateObjectNode::parseAndMerge(
UpdateObjectNode* root,
modifiertable::ModifierType type,
BSONElement modExpr,
- const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters,
std::set<std::string>& foundIdentifiers) {
FieldRef fieldRef;
@@ -194,7 +194,7 @@ StatusWith<bool> UpdateObjectNode::parseAndMerge(
auto status = parseAndMerge(root,
modifiertable::ModifierType::MOD_CONFLICT_PLACEHOLDER,
modExpr,
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
if (!status.isOK()) {
@@ -243,7 +243,7 @@ StatusWith<bool> UpdateObjectNode::parseAndMerge(
// Construct and initialize the leaf node.
auto leaf = modifiertable::makeUpdateLeafNode(type);
invariant(leaf);
- status = leaf->init(modExpr, collator);
+ status = leaf->init(modExpr, expCtx);
if (!status.isOK()) {
return status;
}
diff --git a/src/mongo/db/update/update_object_node.h b/src/mongo/db/update/update_object_node.h
index 81608da70c1..afa75affef2 100644
--- a/src/mongo/db/update/update_object_node.h
+++ b/src/mongo/db/update/update_object_node.h
@@ -60,7 +60,7 @@ public:
UpdateObjectNode* root,
modifiertable::ModifierType type,
BSONElement modExpr,
- const CollatorInterface* collator,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters,
std::set<std::string>& foundIdentifiers);
diff --git a/src/mongo/db/update/update_object_node_test.cpp b/src/mongo/db/update/update_object_node_test.cpp
index 1e699326587..c410553eb9d 100644
--- a/src/mongo/db/update/update_object_node_test.cpp
+++ b/src/mongo/db/update/update_object_node_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/db/json.h"
+#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/update/conflict_placeholder_node.h"
#include "mongo/db/update/rename_node.h"
@@ -49,14 +50,14 @@ using mongo::mutablebson::Element;
TEST(UpdateObjectNodeTest, InvalidPathFailsToParse) {
auto update = fromjson("{$set: {'': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"][""],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -66,42 +67,42 @@ TEST(UpdateObjectNodeTest, InvalidPathFailsToParse) {
TEST(UpdateObjectNodeTest, ValidIncPathParsesSuccessfully) {
auto update = fromjson("{$inc: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_INC,
update["$inc"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidMulPathParsesSuccessfully) {
auto update = fromjson("{$mul: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_MUL,
update["$mul"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidRenamePathParsesSuccessfully) {
auto update = fromjson("{$rename: {'a.b': 'c.d'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -122,140 +123,140 @@ TEST(UpdateObjectNodeTest, ValidRenamePathParsesSuccessfully) {
TEST(UpdateObjectNodeTest, ValidSetPathParsesSuccessfully) {
auto update = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidUnsetPathParsesSuccessfully) {
auto update = fromjson("{$unset: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_UNSET,
update["$unset"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidAddToSetPathParsesSuccessfully) {
auto update = fromjson("{$addToSet: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_ADD_TO_SET,
update["$addToSet"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidPopPathParsesSuccessfully) {
auto update = fromjson("{$pop: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_POP,
update["$pop"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidMaxPathParsesSuccessfully) {
auto update = fromjson("{$max: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_MAX,
update["$max"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidMinPathParsesSuccessfully) {
auto update = fromjson("{$min: {'a.b': 1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_MIN,
update["$min"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidCurrentDatePathParsesSuccessfully) {
auto update = fromjson("{$currentDate: {'a.b': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_CURRENTDATE,
update["$currentDate"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidSetOnInsertPathParsesSuccessfully) {
auto update = fromjson("{$setOnInsert: {'a.b': true}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET_ON_INSERT,
update["$setOnInsert"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ValidPushParsesSuccessfully) {
auto update = fromjson("{$push: {'a.b': {$each: [0, 1], $sort: 1, $position: 0, $slice: 10}}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_PUSH,
update["$push"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, MultiplePositionalElementsFailToParse) {
auto update = fromjson("{$set: {'a.$.b.$': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -266,14 +267,14 @@ TEST(UpdateObjectNodeTest, MultiplePositionalElementsFailToParse) {
TEST(UpdateObjectNodeTest, ParsingSetsPositionalTrue) {
auto update = fromjson("{$set: {'a.$.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_OK(result);
@@ -282,14 +283,14 @@ TEST(UpdateObjectNodeTest, ParsingSetsPositionalTrue) {
TEST(UpdateObjectNodeTest, ParsingSetsPositionalFalse) {
auto update = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_OK(result);
@@ -298,14 +299,14 @@ TEST(UpdateObjectNodeTest, ParsingSetsPositionalFalse) {
TEST(UpdateObjectNodeTest, PositionalElementFirstPositionFailsToParse) {
auto update = fromjson("{$set: {'$': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -316,20 +317,20 @@ TEST(UpdateObjectNodeTest, PositionalElementFirstPositionFailsToParse) {
TEST(UpdateObjectNodeTest, TwoModifiersOnSameFieldFailToParse) {
auto update = fromjson("{$set: {a: 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -339,40 +340,40 @@ TEST(UpdateObjectNodeTest, TwoModifiersOnSameFieldFailToParse) {
TEST(UpdateObjectNodeTest, TwoModifiersOnDifferentFieldsParseSuccessfully) {
auto update = fromjson("{$set: {a: 5, b: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, TwoModifiersWithSameDottedPathFailToParse) {
auto update = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -383,20 +384,20 @@ TEST(UpdateObjectNodeTest, TwoModifiersWithSameDottedPathFailToParse) {
TEST(UpdateObjectNodeTest, FirstModifierPrefixOfSecondFailToParse) {
auto update = fromjson("{$set: {a: 5, 'a.b': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -407,20 +408,20 @@ TEST(UpdateObjectNodeTest, FirstModifierPrefixOfSecondFailToParse) {
TEST(UpdateObjectNodeTest, FirstModifierDottedPrefixOfSecondFailsToParse) {
auto update = fromjson("{$set: {'a.b': 5, 'a.b.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -431,20 +432,20 @@ TEST(UpdateObjectNodeTest, FirstModifierDottedPrefixOfSecondFailsToParse) {
TEST(UpdateObjectNodeTest, SecondModifierPrefixOfFirstFailsToParse) {
auto update = fromjson("{$set: {'a.b': 5, a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -454,20 +455,20 @@ TEST(UpdateObjectNodeTest, SecondModifierPrefixOfFirstFailsToParse) {
TEST(UpdateObjectNodeTest, SecondModifierDottedPrefixOfFirstFailsToParse) {
auto update = fromjson("{$set: {'a.b.c': 5, 'a.b': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -478,80 +479,80 @@ TEST(UpdateObjectNodeTest, SecondModifierDottedPrefixOfFirstFailsToParse) {
TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixParseSuccessfully) {
auto update = fromjson("{$set: {'a.b': 5, 'a.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ModifiersWithCommonDottedPrefixParseSuccessfully) {
auto update = fromjson("{$set: {'a.b.c': 5, 'a.b.d': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixDottedSuffixParseSuccessfully) {
auto update = fromjson("{$set: {'a.b.c': 5, 'a.d.e': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.d.e"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, TwoModifiersOnSamePositionalFieldFailToParse) {
auto update = fromjson("{$set: {'a.$': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -562,60 +563,60 @@ TEST(UpdateObjectNodeTest, TwoModifiersOnSamePositionalFieldFailToParse) {
TEST(UpdateObjectNodeTest, PositionalFieldsWithDifferentPrefixesParseSuccessfully) {
auto update = fromjson("{$set: {'a.$': 5, 'b.$': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["b.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, PositionalAndNonpositionalFieldWithCommonPrefixParseSuccessfully) {
auto update = fromjson("{$set: {'a.$': 5, 'a.0': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, TwoModifiersWithSamePositionalDottedPathFailToParse) {
auto update = fromjson("{$set: {'a.$.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -626,20 +627,20 @@ TEST(UpdateObjectNodeTest, TwoModifiersWithSamePositionalDottedPathFailToParse)
TEST(UpdateObjectNodeTest, FirstModifierPositionalPrefixOfSecondFailsToParse) {
auto update = fromjson("{$set: {'a.$': 5, 'a.$.b': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -650,20 +651,20 @@ TEST(UpdateObjectNodeTest, FirstModifierPositionalPrefixOfSecondFailsToParse) {
TEST(UpdateObjectNodeTest, SecondModifierPositionalPrefixOfFirstFailsToParse) {
auto update = fromjson("{$set: {'a.$.b': 5, 'a.$': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -674,54 +675,54 @@ TEST(UpdateObjectNodeTest, SecondModifierPositionalPrefixOfFirstFailsToParse) {
TEST(UpdateObjectNodeTest, FirstModifierFieldPrefixOfSecondParsesSuccessfully) {
auto update = fromjson("{$set: {'a': 5, 'ab': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["ab"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, SecondModifierFieldPrefixOfSecondParsesSuccessfully) {
auto update = fromjson("{$set: {'ab': 5, 'a': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["ab"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
}
TEST(UpdateObjectNodeTest, IdentifierWithoutArrayFilterFailsToParse) {
auto update = fromjson("{$set: {'a.$[i]': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -732,14 +733,14 @@ TEST(UpdateObjectNodeTest, IdentifierWithoutArrayFilterFailsToParse) {
TEST(UpdateObjectNodeTest, IdentifierInMiddleOfPathWithoutArrayFilterFailsToParse) {
auto update = fromjson("{$set: {'a.$[i].b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -750,14 +751,14 @@ TEST(UpdateObjectNodeTest, IdentifierInMiddleOfPathWithoutArrayFilterFailsToPars
TEST(UpdateObjectNodeTest, EmptyIdentifierParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[]': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_TRUE(foundIdentifiers.empty());
@@ -765,14 +766,14 @@ TEST(UpdateObjectNodeTest, EmptyIdentifierParsesSuccessfully) {
TEST(UpdateObjectNodeTest, EmptyIdentifierInMiddleOfPathParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[].b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_TRUE(foundIdentifiers.empty());
@@ -781,15 +782,15 @@ TEST(UpdateObjectNodeTest, EmptyIdentifierInMiddleOfPathParsesSuccessfully) {
TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[i]': 5}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -799,15 +800,15 @@ TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterParsesSuccessfully) {
TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterInMiddleOfPathParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[i].b': 5}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -817,15 +818,15 @@ TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterInMiddleOfPathParsesSuccessf
TEST(UpdateObjectNodeTest, IdentifierInFirstPositionFailsToParse) {
auto update = fromjson("{$set: {'$[i]': 5}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -838,15 +839,15 @@ TEST(UpdateObjectNodeTest, IdentifierInFirstPositionFailsToParse) {
TEST(UpdateObjectNodeTest, IdentifierInFirstPositionWithSuffixFailsToParse) {
auto update = fromjson("{$set: {'$[i].a': 5}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["$[i].a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -859,15 +860,15 @@ TEST(UpdateObjectNodeTest, IdentifierInFirstPositionWithSuffixFailsToParse) {
TEST(UpdateObjectNodeTest, CreateObjectNodeInSamePositionAsArrayNodeFailsToParse) {
auto update = fromjson("{$set: {'a.$[i]': 5, 'a.0': 6}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -875,7 +876,7 @@ TEST(UpdateObjectNodeTest, CreateObjectNodeInSamePositionAsArrayNodeFailsToParse
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -887,21 +888,21 @@ TEST(UpdateObjectNodeTest, CreateObjectNodeInSamePositionAsArrayNodeFailsToParse
TEST(UpdateObjectNodeTest, CreateArrayNodeInSamePositionAsObjectNodeFailsToParse) {
auto update = fromjson("{$set: {'a.0': 5, 'a.$[i]': 6}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -913,15 +914,15 @@ TEST(UpdateObjectNodeTest, CreateArrayNodeInSamePositionAsObjectNodeFailsToParse
TEST(UpdateObjectNodeTest, CreateLeafNodeInSamePositionAsArrayNodeFailsToParse) {
auto update = fromjson("{$set: {'a.$[i]': 5, a: 6}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -929,7 +930,7 @@ TEST(UpdateObjectNodeTest, CreateLeafNodeInSamePositionAsArrayNodeFailsToParse)
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -940,21 +941,21 @@ TEST(UpdateObjectNodeTest, CreateLeafNodeInSamePositionAsArrayNodeFailsToParse)
TEST(UpdateObjectNodeTest, CreateArrayNodeInSamePositionAsLeafNodeFailsToParse) {
auto update = fromjson("{$set: {a: 5, 'a.$[i]': 6}}");
auto arrayFilter = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -967,16 +968,16 @@ TEST(UpdateObjectNodeTest, CreateTwoChildrenOfArrayNodeParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[i]': 5, 'a.$[j]': 6}}");
auto arrayFilterI = fromjson("{i: 0}");
auto arrayFilterJ = fromjson("{j: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -984,7 +985,7 @@ TEST(UpdateObjectNodeTest, CreateTwoChildrenOfArrayNodeParsesSuccessfully) {
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 2U);
@@ -996,15 +997,15 @@ TEST(UpdateObjectNodeTest, ConflictAtArrayNodeChildFailsToParse) {
auto update1 = fromjson("{$set: {'a.$[i]': 5}}");
auto update2 = fromjson("{$set: {'a.$[i]': 6}}");
auto arrayFilterI = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update1["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -1012,7 +1013,7 @@ TEST(UpdateObjectNodeTest, ConflictAtArrayNodeChildFailsToParse) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update2["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -1024,15 +1025,15 @@ TEST(UpdateObjectNodeTest, ConflictAtArrayNodeChildFailsToParse) {
TEST(UpdateObjectNodeTest, ConflictThroughArrayNodeChildFailsToParse) {
auto update = fromjson("{$set: {'a.$[i].b': 5, 'a.$[i].b.c': 6}}");
auto arrayFilterI = fromjson("{i: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -1040,7 +1041,7 @@ TEST(UpdateObjectNodeTest, ConflictThroughArrayNodeChildFailsToParse) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -1053,16 +1054,16 @@ TEST(UpdateObjectNodeTest, NoConflictDueToDifferentArrayNodeChildrenParsesSucces
auto update = fromjson("{$set: {'a.$[i].b': 5, 'a.$[j].b.c': 6}}");
auto arrayFilterI = fromjson("{i: 0}");
auto arrayFilterJ = fromjson("{j: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 1U);
@@ -1070,7 +1071,7 @@ TEST(UpdateObjectNodeTest, NoConflictDueToDifferentArrayNodeChildrenParsesSucces
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[j].b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 2U);
@@ -1082,16 +1083,16 @@ TEST(UpdateObjectNodeTest, MultipleArrayNodesAlongPathParsesSuccessfully) {
auto update = fromjson("{$set: {'a.$[i].$[j].$[i]': 5}}");
auto arrayFilterI = fromjson("{i: 0}");
auto arrayFilterJ = fromjson("{j: 0}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.$[i].$[j].$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_EQ(foundIdentifiers.size(), 2U);
@@ -1121,20 +1122,20 @@ TEST(UpdateObjectNodeTest, DistinctFieldsMergeCorrectly) {
auto setUpdate1 = fromjson("{$set: {'a': 5}}");
auto setUpdate2 = fromjson("{$set: {'ab': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["ab"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1151,20 +1152,20 @@ TEST(UpdateObjectNodeTest, NestedMergeSucceeds) {
auto setUpdate1 = fromjson("{$set: {'a.c': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.d': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1187,20 +1188,20 @@ TEST(UpdateObjectNodeTest, DoublyNestedMergeSucceeds) {
auto setUpdate1 = fromjson("{$set: {'a.b.c': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.b.d': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.b.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1229,20 +1230,20 @@ TEST(UpdateObjectNodeTest, FieldAndPositionalMergeCorrectly) {
auto setUpdate1 = fromjson("{$set: {'a.b': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1266,20 +1267,20 @@ TEST(UpdateObjectNodeTest, MergeThroughPositionalSucceeds) {
auto setUpdate1 = fromjson("{$set: {'a.$.b': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$.c': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1308,20 +1309,20 @@ TEST(UpdateObjectNodeTest, TopLevelConflictFails) {
auto setUpdate1 = fromjson("{$set: {'a': 5}}");
auto setUpdate2 = fromjson("{$set: {'a': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1337,20 +1338,20 @@ TEST(UpdateObjectNodeTest, NestedConflictFails) {
auto setUpdate1 = fromjson("{$set: {'a.b': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.b': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1366,20 +1367,20 @@ TEST(UpdateObjectNodeTest, LeftPrefixMergeFails) {
auto setUpdate1 = fromjson("{$set: {'a.b': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.b.c': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1395,20 +1396,20 @@ TEST(UpdateObjectNodeTest, RightPrefixMergeFails) {
auto setUpdate1 = fromjson("{$set: {'a.b.c': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.b': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1424,20 +1425,20 @@ TEST(UpdateObjectNodeTest, LeftPrefixMergeThroughPositionalFails) {
auto setUpdate1 = fromjson("{$set: {'a.$.c': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$.c.d': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$.c.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1453,20 +1454,20 @@ TEST(UpdateObjectNodeTest, RightPrefixMergeThroughPositionalFails) {
auto setUpdate1 = fromjson("{$set: {'a.$.c.d': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$.c': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$.c.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1482,20 +1483,20 @@ TEST(UpdateObjectNodeTest, MergeWithConflictingPositionalFails) {
auto setUpdate1 = fromjson("{$set: {'a.$': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1513,25 +1514,25 @@ DEATH_TEST(UpdateObjectNodeTest,
auto setUpdate1 = fromjson("{$set: {'a.$[i]': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$[j]': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilterI = fromjson("{i: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters1;
- arrayFilters1["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
+ arrayFilters1["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
auto arrayFilterJ = fromjson("{j: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters2;
- arrayFilters2["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters2["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters1,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$[j]"],
- collator,
+ expCtx,
arrayFilters2,
foundIdentifiers));
@@ -1542,22 +1543,22 @@ TEST(UpdateObjectNodeTest, MergingArrayNodeWithObjectNodeFails) {
auto setUpdate1 = fromjson("{$set: {'a.$[i]': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.b': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilter = fromjson("{i: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1573,22 +1574,22 @@ TEST(UpdateObjectNodeTest, MergingArrayNodeWithLeafNodeFails) {
auto setUpdate1 = fromjson("{$set: {'a.$[i]': 5}}");
auto setUpdate2 = fromjson("{$set: {'a': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilter = fromjson("{i: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1604,24 +1605,24 @@ TEST(UpdateObjectNodeTest, MergingTwoArrayNodesSucceeds) {
auto setUpdate1 = fromjson("{$set: {'a.$[i]': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$[j]': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilterI = fromjson("{i: 0}");
auto arrayFilterJ = fromjson("{j: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator));
- arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, expCtx));
+ arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$[j]"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1644,22 +1645,22 @@ TEST(UpdateObjectNodeTest, MergeConflictThroughArrayNodesFails) {
auto setUpdate1 = fromjson("{$set: {'a.$[i].b.c': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$[i].b': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilter = fromjson("{i: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i].b.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1675,22 +1676,22 @@ TEST(UpdateObjectNodeTest, NoMergeConflictThroughArrayNodesSucceeds) {
auto setUpdate1 = fromjson("{$set: {'a.$[i].b': 5}}");
auto setUpdate2 = fromjson("{$set: {'a.$[i].c': 6}}");
FieldRef fakeFieldRef("root");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
auto arrayFilter = fromjson("{i: 0}");
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator));
+ arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, expCtx));
std::set<std::string> foundIdentifiers;
UpdateObjectNode setRoot1, setRoot2;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1,
modifiertable::ModifierType::MOD_SET,
setUpdate1["$set"]["a.$[i].b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot2,
modifiertable::ModifierType::MOD_SET,
setUpdate2["$set"]["a.$[i].c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1717,14 +1718,14 @@ TEST(UpdateObjectNodeTest, NoMergeConflictThroughArrayNodesSucceeds) {
TEST_F(UpdateObjectNodeTest, ApplyCreateField) {
auto setUpdate = fromjson("{$set: {b: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1740,14 +1741,14 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateField) {
TEST_F(UpdateObjectNodeTest, ApplyExistingField) {
auto setUpdate = fromjson("{$set: {a: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1763,32 +1764,32 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingField) {
TEST_F(UpdateObjectNodeTest, ApplyExistingAndNonexistingFields) {
auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7, d: 8}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1804,32 +1805,32 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingAndNonexistingFields) {
TEST_F(UpdateObjectNodeTest, ApplyExistingNestedPaths) {
auto setUpdate = fromjson("{$set: {'a.b': 6, 'a.c': 7, 'b.d': 8, 'b.e': 9}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b.e"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1846,32 +1847,32 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingNestedPaths) {
TEST_F(UpdateObjectNodeTest, ApplyCreateNestedPaths) {
auto setUpdate = fromjson("{$set: {'a.b': 6, 'a.c': 7, 'b.d': 8, 'b.e': 9}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b.e"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1888,26 +1889,26 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateNestedPaths) {
TEST_F(UpdateObjectNodeTest, ApplyCreateDeeplyNestedPaths) {
auto setUpdate = fromjson("{$set: {'a.b.c.d': 6, 'a.b.c.e': 7, 'a.f': 8}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b.c.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b.c.e"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.f"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1924,38 +1925,38 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateDeeplyNestedPaths) {
TEST_F(UpdateObjectNodeTest, ChildrenShouldBeAppliedInAlphabeticalOrder) {
auto setUpdate = fromjson("{$set: {a: 5, d: 6, c: 7, b: 8, z: 9}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["z"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -1972,19 +1973,21 @@ TEST_F(UpdateObjectNodeTest, ChildrenShouldBeAppliedInAlphabeticalOrder) {
TEST_F(UpdateObjectNodeTest, CollatorShouldNotAffectUpdateOrder) {
auto setUpdate = fromjson("{$set: {abc: 5, cba: 6}}");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["abc"],
- &collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["cba"],
- &collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2000,26 +2003,26 @@ TEST_F(UpdateObjectNodeTest, CollatorShouldNotAffectUpdateOrder) {
TEST_F(UpdateObjectNodeTest, ApplyNoop) {
auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2037,26 +2040,26 @@ TEST_F(UpdateObjectNodeTest, ApplyNoop) {
TEST_F(UpdateObjectNodeTest, ApplySomeChildrenNoops) {
auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2074,14 +2077,14 @@ TEST_F(UpdateObjectNodeTest, ApplySomeChildrenNoops) {
TEST_F(UpdateObjectNodeTest, ApplyBlockingElement) {
auto setUpdate = fromjson("{$set: {'a.b': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2095,20 +2098,20 @@ TEST_F(UpdateObjectNodeTest, ApplyBlockingElement) {
TEST_F(UpdateObjectNodeTest, ApplyBlockingElementFromReplication) {
auto setUpdate = fromjson("{$set: {'a.b': 5, b: 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2125,14 +2128,14 @@ TEST_F(UpdateObjectNodeTest, ApplyBlockingElementFromReplication) {
TEST_F(UpdateObjectNodeTest, ApplyPositionalMissingMatchedField) {
auto setUpdate = fromjson("{$set: {'a.$': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2147,20 +2150,20 @@ TEST_F(UpdateObjectNodeTest, ApplyPositionalMissingMatchedField) {
TEST_F(UpdateObjectNodeTest, ApplyMergePositionalChild) {
auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2177,32 +2180,32 @@ TEST_F(UpdateObjectNodeTest, ApplyMergePositionalChild) {
TEST_F(UpdateObjectNodeTest, ApplyOrderMergedPositionalChild) {
auto setUpdate = fromjson("{$set: {'a.2': 5, 'a.1.b': 6, 'a.0': 7, 'a.$.c': 8}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.2"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.1.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2220,20 +2223,20 @@ TEST_F(UpdateObjectNodeTest, ApplyOrderMergedPositionalChild) {
TEST_F(UpdateObjectNodeTest, ApplyMergeConflictWithPositionalChild) {
auto setUpdate = fromjson("{$set: {'a.0': 5, 'a.$': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2248,26 +2251,26 @@ TEST_F(UpdateObjectNodeTest, ApplyMergeConflictWithPositionalChild) {
TEST_F(UpdateObjectNodeTest, ApplyDoNotMergePositionalChild) {
auto setUpdate = fromjson("{$set: {'a.0': 5, 'a.2': 6, 'a.$': 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.2"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2284,26 +2287,26 @@ TEST_F(UpdateObjectNodeTest, ApplyDoNotMergePositionalChild) {
TEST_F(UpdateObjectNodeTest, ApplyPositionalChildLast) {
auto setUpdate = fromjson("{$set: {'a.$': 5, 'a.0': 6, 'a.1': 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.1"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2320,20 +2323,20 @@ TEST_F(UpdateObjectNodeTest, ApplyPositionalChildLast) {
TEST_F(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) {
auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2361,26 +2364,26 @@ TEST_F(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) {
TEST_F(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) {
auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6, 'a.1.d': 7}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.0.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.$.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.1.d"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2415,14 +2418,14 @@ TEST_F(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) {
*/
TEST_F(UpdateObjectNodeTest, ApplyToArrayByIndexWithLeadingZero) {
auto setUpdate = fromjson("{$set: {'a.02': 2}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.02"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2444,20 +2447,20 @@ TEST_F(UpdateObjectNodeTest, ApplyToArrayByIndexWithLeadingZero) {
*/
TEST_F(UpdateObjectNodeTest, ApplyMultipleArrayUpdates) {
auto setUpdate = fromjson("{$set: {'a.2': 2, 'a.10': 10}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.2"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.10"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2475,14 +2478,14 @@ TEST_F(UpdateObjectNodeTest, ApplyMultipleArrayUpdates) {
TEST_F(UpdateObjectNodeTest, ApplyUpdateToNonViablePathInArray) {
auto setUpdate = fromjson("{$set: {'a.b': 3}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
setUpdate["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2496,20 +2499,20 @@ TEST_F(UpdateObjectNodeTest, ApplyUpdateToNonViablePathInArray) {
TEST_F(UpdateObjectNodeTest, SetAndPopModifiersWithCommonPrefixApplySuccessfully) {
auto update = fromjson("{$set: {'a.b': 5}, $pop: {'a.c': -1}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_POP,
update["$pop"]["a.c"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
@@ -2523,7 +2526,7 @@ TEST_F(UpdateObjectNodeTest, SetAndPopModifiersWithCommonPrefixApplySuccessfully
}
TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
@@ -2535,7 +2538,7 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2550,7 +2553,7 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2565,7 +2568,7 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2580,7 +2583,7 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a.b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2590,14 +2593,14 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) {
TEST(ParseRenameTest, RenameToNonUpdatablePathFails) {
auto update = fromjson("{$rename: {'a': 'b.'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2608,14 +2611,14 @@ TEST(ParseRenameTest, RenameToNonUpdatablePathFails) {
TEST(ParseRenameTest, RenameFromNonUpdatablePathFails) {
auto update = fromjson("{$rename: {'.a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"][".a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2626,14 +2629,14 @@ TEST(ParseRenameTest, RenameFromNonUpdatablePathFails) {
TEST(ParseRenameTest, RenameToNonStringPathFails) {
auto update = fromjson("{$rename: {'a': 5}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2650,14 +2653,14 @@ TEST(ParseRenameTest, RenameToNonStringPathFails) {
*/
TEST(ParseRenameTest, RenameWithSameNameFails) {
auto update = fromjson("{$rename: {'a': 'a'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2668,14 +2671,14 @@ TEST(ParseRenameTest, RenameWithSameNameFails) {
TEST(ParseRenameTest, RenameUpwardFails) {
auto update = fromjson("{$rename: {'b.a': 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["b.a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2686,14 +2689,14 @@ TEST(ParseRenameTest, RenameUpwardFails) {
TEST(ParseRenameTest, RenameDownwardFails) {
auto update = fromjson("{$rename: {'b': 'b.a'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2704,20 +2707,20 @@ TEST(ParseRenameTest, RenameDownwardFails) {
TEST(ParseRenameTest, ConflictWithRenameSourceFailsToParse) {
auto update = fromjson("{$set: {a: 5}, $rename: {a: 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
@@ -2727,20 +2730,20 @@ TEST(ParseRenameTest, ConflictWithRenameSourceFailsToParse) {
TEST(ParseRenameTest, ConflictWithRenameDestinationFailsToParse) {
auto update = fromjson("{$set: {b: 5}, $rename: {a: 'b'}}");
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
std::set<std::string> foundIdentifiers;
UpdateObjectNode root;
ASSERT_OK(UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_SET,
update["$set"]["b"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers));
auto result = UpdateObjectNode::parseAndMerge(&root,
modifiertable::ModifierType::MOD_RENAME,
update["$rename"]["a"],
- collator,
+ expCtx,
arrayFilters,
foundIdentifiers);
ASSERT_NOT_OK(result);
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index 20ddd6066b4..59546ed05df 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -186,7 +186,7 @@ Status ViewCatalog::_upsertIntoGraph(OperationContext* opCtx, const ViewDefiniti
request,
CollatorInterface::cloneCollator(viewDef.defaultCollator()),
std::move(resolvedNamespaces));
- auto pipelineStatus = Pipeline::parse(viewDef.pipeline(), expCtx);
+ auto pipelineStatus = Pipeline::parse(viewDef.pipeline(), std::move(expCtx));
if (!pipelineStatus.isOK()) {
uassert(40255,
str::stream() << "Invalid pipeline for view " << viewDef.name().ns() << "; "
diff --git a/src/mongo/dbtests/SConscript b/src/mongo/dbtests/SConscript
index ca98dec10cb..156d91111c0 100644
--- a/src/mongo/dbtests/SConscript
+++ b/src/mongo/dbtests/SConscript
@@ -126,6 +126,7 @@ dbtest = env.Program(
"$BUILD_DIR/mongo/db/pipeline/document_value_test_util",
"$BUILD_DIR/mongo/db/query/collation/collator_interface_mock",
"$BUILD_DIR/mongo/db/query/query",
+ "$BUILD_DIR/mongo/db/query/query_planner_test_lib",
"$BUILD_DIR/mongo/db/query/query_test_service_context",
"$BUILD_DIR/mongo/db/repl/drop_pending_collection_reaper",
"$BUILD_DIR/mongo/db/repl/repl_coordinator_global",
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 9d5fc0b5162..ab3ed2b08a0 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -325,8 +325,7 @@ TEST_F(DocumentSourceCursorTest, TailableAwaitDataCursorStillUsableAfterTimeout)
collScanParams.collection = readLock.getCollection();
collScanParams.tailable = true;
auto filter = BSON("a" << 1);
- auto matchExpression =
- uassertStatusOK(MatchExpressionParser::parse(filter, ctx()->getCollator()));
+ auto matchExpression = uassertStatusOK(MatchExpressionParser::parse(filter, ctx()));
auto collectionScan = stdx::make_unique<CollectionScan>(
opCtx(), collScanParams, workingSet.get(), matchExpression.get());
auto queryRequest = stdx::make_unique<QueryRequest>(nss);
@@ -364,8 +363,7 @@ TEST_F(DocumentSourceCursorTest, NonAwaitDataCursorShouldErrorAfterTimeout) {
CollectionScanParams collScanParams;
collScanParams.collection = readLock.getCollection();
auto filter = BSON("a" << 1);
- auto matchExpression =
- uassertStatusOK(MatchExpressionParser::parse(filter, ctx()->getCollator()));
+ auto matchExpression = uassertStatusOK(MatchExpressionParser::parse(filter, ctx()));
auto collectionScan = stdx::make_unique<CollectionScan>(
opCtx(), collScanParams, workingSet.get(), matchExpression.get());
auto queryRequest = stdx::make_unique<QueryRequest>(nss);
@@ -405,8 +403,7 @@ TEST_F(DocumentSourceCursorTest, TailableAwaitDataCursorShouldErrorAfterBeingKil
collScanParams.collection = readLock.getCollection();
collScanParams.tailable = true;
auto filter = BSON("a" << 1);
- auto matchExpression =
- uassertStatusOK(MatchExpressionParser::parse(filter, ctx()->getCollator()));
+ auto matchExpression = uassertStatusOK(MatchExpressionParser::parse(filter, ctx()));
auto collectionScan = stdx::make_unique<CollectionScan>(
opCtx(), collScanParams, workingSet.get(), matchExpression.get());
auto queryRequest = stdx::make_unique<QueryRequest>(nss);
@@ -444,8 +441,7 @@ TEST_F(DocumentSourceCursorTest, NormalCursorShouldErrorAfterBeingKilled) {
CollectionScanParams collScanParams;
collScanParams.collection = readLock.getCollection();
auto filter = BSON("a" << 1);
- auto matchExpression =
- uassertStatusOK(MatchExpressionParser::parse(filter, ctx()->getCollator()));
+ auto matchExpression = uassertStatusOK(MatchExpressionParser::parse(filter, ctx()));
auto collectionScan = stdx::make_unique<CollectionScan>(
opCtx(), collScanParams, workingSet.get(), matchExpression.get());
auto queryRequest = stdx::make_unique<QueryRequest>(nss);
diff --git a/src/mongo/dbtests/matchertests.cpp b/src/mongo/dbtests/matchertests.cpp
index 3d20d60fde3..ee02b4b24de 100644
--- a/src/mongo/dbtests/matchertests.cpp
+++ b/src/mongo/dbtests/matchertests.cpp
@@ -61,8 +61,8 @@ class Basic {
public:
void run() {
BSONObj query = fromjson("{\"a\":\"b\"}");
- const CollatorInterface* collator = nullptr;
- M m(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(query, expCtx);
ASSERT(m.matches(fromjson("{\"a\":\"b\"}")));
}
};
@@ -72,8 +72,8 @@ class DoubleEqual {
public:
void run() {
BSONObj query = fromjson("{\"a\":5}");
- const CollatorInterface* collator = nullptr;
- M m(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(query, expCtx);
ASSERT(m.matches(fromjson("{\"a\":5}")));
}
};
@@ -84,8 +84,8 @@ public:
void run() {
BSONObjBuilder query;
query.append("a", 5);
- const CollatorInterface* collator = nullptr;
- M m(query.done(), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(query.done(), expCtx);
ASSERT(m.matches(fromjson("{\"a\":5}")));
}
};
@@ -95,8 +95,8 @@ class MixedNumericGt {
public:
void run() {
BSONObj query = fromjson("{\"a\":{\"$gt\":4}}");
- const CollatorInterface* collator = nullptr;
- M m(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(query, expCtx);
BSONObjBuilder b;
b.append("a", 5);
ASSERT(m.matches(b.done()));
@@ -111,8 +111,8 @@ public:
ASSERT_EQUALS(4, query["a"].embeddedObject()["$in"].embeddedObject()["0"].number());
ASSERT_EQUALS(NumberInt, query["a"].embeddedObject()["$in"].embeddedObject()["0"].type());
- const CollatorInterface* collator = nullptr;
- M m(query, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(query, expCtx);
{
BSONObjBuilder b;
@@ -139,8 +139,8 @@ template <typename M>
class MixedNumericEmbedded {
public:
void run() {
- const CollatorInterface* collator = nullptr;
- M m(BSON("a" << BSON("x" << 1)), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(BSON("a" << BSON("x" << 1)), expCtx);
ASSERT(m.matches(BSON("a" << BSON("x" << 1))));
ASSERT(m.matches(BSON("a" << BSON("x" << 1.0))));
}
@@ -150,8 +150,8 @@ template <typename M>
class Size {
public:
void run() {
- const CollatorInterface* collator = nullptr;
- M m(fromjson("{a:{$size:4}}"), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(fromjson("{a:{$size:4}}"), expCtx);
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']}")));
@@ -163,8 +163,8 @@ template <typename M>
class WithinBox {
public:
void run() {
- const CollatorInterface* collator = nullptr;
- M m(fromjson("{loc:{$within:{$box:[{x: 4, y:4},[6,6]]}}}"), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(fromjson("{loc:{$within:{$box:[{x: 4, y:4},[6,6]]}}}"), expCtx);
ASSERT(!m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: [4,4]}")));
ASSERT(m.matches(fromjson("{loc: [5,5]}")));
@@ -177,8 +177,8 @@ template <typename M>
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]]}}}"), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(fromjson("{loc:{$within:{$polygon:[{x:0,y:0},[0,5],[5,5],[5,0]]}}}"), expCtx);
ASSERT(m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: [4,4]}")));
ASSERT(m.matches(fromjson("{loc: {x:5,y:5}}")));
@@ -191,8 +191,8 @@ template <typename M>
class WithinCenter {
public:
void run() {
- const CollatorInterface* collator = nullptr;
- M m(fromjson("{loc:{$within:{$center:[{x:30,y:30},10]}}}"), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(fromjson("{loc:{$within:{$center:[{x:30,y:30},10]}}}"), expCtx);
ASSERT(!m.matches(fromjson("{loc: [3,4]}")));
ASSERT(m.matches(fromjson("{loc: {x:30,y:30}}")));
ASSERT(m.matches(fromjson("{loc: [20,30]}")));
@@ -208,8 +208,8 @@ template <typename M>
class ElemMatchKey {
public:
void run() {
- const CollatorInterface* collator = nullptr;
- M matcher(BSON("a.b" << 1), collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M matcher(BSON("a.b" << 1), expCtx);
MatchDetails details;
details.requestElemMatchKey();
ASSERT(!details.hasElemMatchKey());
@@ -230,10 +230,10 @@ public:
AutoGetCollectionForReadCommand ctx(&opCtx, nss);
const CollatorInterface* collator = nullptr;
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(opCtxPtr.get(), collator));
M m(BSON("$where"
<< "function(){ return this.a == 1; }"),
- collator,
expCtx,
ExtensionsCallbackReal(&opCtx, &nss),
MatchExpressionParser::AllowedFeatures::kJavascript);
@@ -246,8 +246,8 @@ template <typename M>
class TimingBase {
public:
long dotime(const BSONObj& patt, const BSONObj& obj) {
- const CollatorInterface* collator = nullptr;
- M m(patt, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ M m(patt, expCtx);
Timer t;
for (int i = 0; i < 900000; i++) {
if (!m.matches(obj)) {
@@ -277,10 +277,10 @@ template <typename M>
class NullCollator {
public:
void run() {
- const CollatorInterface* collator = nullptr;
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
M matcher(BSON("a"
<< "string"),
- collator);
+ expCtx);
ASSERT(!matcher.matches(BSON("a"
<< "string2")));
}
@@ -292,9 +292,11 @@ class Collator {
public:
void run() {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ expCtx->setCollator(&collator);
M matcher(BSON("a"
<< "string"),
- &collator);
+ expCtx);
ASSERT(matcher.matches(BSON("a"
<< "string2")));
}
diff --git a/src/mongo/dbtests/query_stage_collscan.cpp b/src/mongo/dbtests/query_stage_collscan.cpp
index d17dbdbbcfa..16d016f8eb9 100644
--- a/src/mongo/dbtests/query_stage_collscan.cpp
+++ b/src/mongo/dbtests/query_stage_collscan.cpp
@@ -93,8 +93,10 @@ public:
// Make the filter.
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(&_opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filterObj, collator);
+ MatchExpressionParser::parse(filterObj, expCtx);
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 130cd6e3e4b..e28d388d0aa 100644
--- a/src/mongo/dbtests/query_stage_count.cpp
+++ b/src/mongo/dbtests/query_stage_count.cpp
@@ -149,8 +149,10 @@ public:
unique_ptr<WorkingSet> ws(new WorkingSet);
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(&_opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(request.getQuery(), collator);
+ MatchExpressionParser::parse(request.getQuery(), expCtx);
ASSERT(statusWithMatcher.isOK());
unique_ptr<MatchExpression> expression = std::move(statusWithMatcher.getValue());
diff --git a/src/mongo/dbtests/query_stage_fetch.cpp b/src/mongo/dbtests/query_stage_fetch.cpp
index e866d2df9c9..ae1dd71152e 100644
--- a/src/mongo/dbtests/query_stage_fetch.cpp
+++ b/src/mongo/dbtests/query_stage_fetch.cpp
@@ -194,8 +194,10 @@ public:
// Make the filter.
BSONObj filterObj = BSON("foo" << 6);
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(&_opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filterObj, collator);
+ MatchExpressionParser::parse(filterObj, expCtx);
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 dd1fc50b924..a76b67ac9d0 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -164,7 +164,9 @@ TEST_F(QueryStageMultiPlanTest, MPSCollectionScanVsHighlySelectiveIXScan) {
// Make the filter.
BSONObj filterObj = BSON("foo" << 7);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(_opCtx.get(), collator));
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, expCtx);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filter = std::move(statusWithMatcher.getValue());
// Make the stage.
@@ -458,7 +460,9 @@ TEST_F(QueryStageMultiPlanTest, ShouldReportErrorIfExceedsTimeLimitDuringPlannin
// Make the filter.
BSONObj filterObj = BSON("foo" << 7);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(_opCtx.get(), collator));
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, expCtx);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filter = std::move(statusWithMatcher.getValue());
// Make the stage.
@@ -521,7 +525,9 @@ TEST_F(QueryStageMultiPlanTest, ShouldReportErrorIfKilledDuringPlanning) {
// Make the filter.
BSONObj filterObj = BSON("foo" << 7);
const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, collator);
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(_opCtx.get(), collator));
+ StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(filterObj, expCtx);
verify(statusWithMatcher.isOK());
unique_ptr<MatchExpression> filter = std::move(statusWithMatcher.getValue());
// Make the stage.
diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp
index 3b2e474e35a..279eafac9c7 100644
--- a/src/mongo/dbtests/query_stage_subplan.cpp
+++ b/src/mongo/dbtests/query_stage_subplan.cpp
@@ -452,8 +452,8 @@ TEST_F(QueryStageSubplanTest, QueryStageSubplanRewriteToRootedOr) {
// Rewrite (AND (OR a b) e) => (OR (AND a e) (AND b e))
{
BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, expCtx);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
@@ -469,8 +469,8 @@ TEST_F(QueryStageSubplanTest, QueryStageSubplanRewriteToRootedOr) {
// Rewrite (AND (OR a b) e f) => (OR (AND a e f) (AND b e f))
{
BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1, f:1}");
- const CollatorInterface* collator = nullptr;
- StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, expCtx);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
@@ -486,8 +486,8 @@ TEST_F(QueryStageSubplanTest, QueryStageSubplanRewriteToRootedOr) {
// Rewrite (AND (OR (AND a b) (AND c d) e f) => (OR (AND a b e f) (AND c d e f))
{
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, collator);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression expr = MatchExpressionParser::parse(queryObj, expCtx);
ASSERT_OK(expr.getStatus());
std::unique_ptr<MatchExpression> rewrittenExpr =
SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index 6b7893798e5..8f6e5a52373 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -82,8 +82,10 @@ public:
AutoGetCollectionForReadCommand ctx(&_opCtx, NamespaceString(ns()));
const CollatorInterface* collator = nullptr;
+ const boost::intrusive_ptr<ExpressionContext> expCtx(
+ new ExpressionContext(&_opCtx, collator));
StatusWithMatchExpression statusWithMatcher =
- MatchExpressionParser::parse(filterObj, collator);
+ MatchExpressionParser::parse(filterObj, expCtx);
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 7ccd6058545..d53d3a2daf4 100644
--- a/src/mongo/dbtests/query_stage_update.cpp
+++ b/src/mongo/dbtests/query_stage_update.cpp
@@ -189,7 +189,8 @@ public:
OldClientWriteContext ctx(&_opCtx, nss.ns());
CurOp& curOp = *CurOp::get(_opCtx);
OpDebug* opDebug = &curOp.debug();
- UpdateDriver driver((UpdateDriver::Options()));
+ const CollatorInterface* collator = nullptr;
+ UpdateDriver driver((UpdateDriver::Options(new ExpressionContext(&_opCtx, collator))));
Collection* collection = ctx.getCollection();
// Collection should be empty.
@@ -259,7 +260,8 @@ public:
CurOp& curOp = *CurOp::get(_opCtx);
OpDebug* opDebug = &curOp.debug();
- UpdateDriver driver((UpdateDriver::Options()));
+ const CollatorInterface* collator = nullptr;
+ UpdateDriver driver((UpdateDriver::Options(new ExpressionContext(&_opCtx, collator))));
Database* db = ctx.db();
Collection* coll = db->getCollection(&_opCtx, nss);
@@ -377,7 +379,8 @@ public:
Collection* coll = ctx.getCollection();
UpdateLifecycleImpl updateLifecycle(nss);
UpdateRequest request(nss);
- UpdateDriver driver((UpdateDriver::Options()));
+ const CollatorInterface* collator = nullptr;
+ UpdateDriver driver((UpdateDriver::Options(new ExpressionContext(&_opCtx, collator))));
const int targetDocIndex = 0; // We'll be working with the first doc in the collection.
const BSONObj query = BSON("foo" << BSON("$gte" << targetDocIndex));
const auto ws = make_unique<WorkingSet>();
@@ -467,7 +470,8 @@ public:
Collection* coll = ctx.getCollection();
UpdateLifecycleImpl updateLifecycle(nss);
UpdateRequest request(nss);
- UpdateDriver driver((UpdateDriver::Options()));
+ const CollatorInterface* collator = nullptr;
+ UpdateDriver driver((UpdateDriver::Options(new ExpressionContext(&_opCtx, collator))));
const int targetDocIndex = 10;
const BSONObj query = BSON("foo" << BSON("$gte" << targetDocIndex));
const auto ws = make_unique<WorkingSet>();
@@ -553,7 +557,8 @@ public:
Collection* coll = ctx.getCollection();
UpdateLifecycleImpl updateLifecycle(nss);
UpdateRequest request(nss);
- UpdateDriver driver((UpdateDriver::Options()));
+ const CollatorInterface* collator = nullptr;
+ UpdateDriver driver((UpdateDriver::Options(new ExpressionContext(&_opCtx, collator))));
const BSONObj query = BSONObj();
const auto ws = make_unique<WorkingSet>();
const unique_ptr<CanonicalQuery> cq(canonicalize(query));
diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript
index 4d001a6da9a..e3e7a6ce41b 100644
--- a/src/mongo/s/SConscript
+++ b/src/mongo/s/SConscript
@@ -305,6 +305,7 @@ env.CppUnitTest(
'chunk_manager_query_test.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/query/query_test_service_context',
'$BUILD_DIR/mongo/s/catalog/sharding_catalog_test_fixture',
'coreshard',
]