diff options
author | Natalia Jacobowitz <natalia.jacobowitz@mongodb.com> | 2017-07-20 18:23:58 -0400 |
---|---|---|
committer | Natalia Jacobowitz <natalia.jacobowitz@mongodb.com> | 2017-07-25 14:30:02 -0400 |
commit | 3b54aa39c670c176541bdfdb37d0d3fcb2f1e9ea (patch) | |
tree | 8f5a289fad5ccb75e2a23a3f8b5c1b1466bfe91c /src/mongo/db/update | |
parent | 68bca92abdd01a91dd3606cc3f5708f74d084b86 (diff) | |
download | mongo-3b54aa39c670c176541bdfdb37d0d3fcb2f1e9ea.tar.gz |
SERVER-30243: Move ArrayFilter class to expressions library, allowing for future re-usability with JSON Schema
Diffstat (limited to 'src/mongo/db/update')
-rw-r--r-- | src/mongo/db/update/SConscript | 19 | ||||
-rw-r--r-- | src/mongo/db/update/array_filter.cpp | 128 | ||||
-rw-r--r-- | src/mongo/db/update/array_filter.h | 69 | ||||
-rw-r--r-- | src/mongo/db/update/array_filter_test.cpp | 180 | ||||
-rw-r--r-- | src/mongo/db/update/update_array_node.h | 7 | ||||
-rw-r--r-- | src/mongo/db/update/update_array_node_test.cpp | 112 | ||||
-rw-r--r-- | src/mongo/db/update/update_driver.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/update/update_driver.h | 7 | ||||
-rw-r--r-- | src/mongo/db/update/update_driver_test.cpp | 24 | ||||
-rw-r--r-- | src/mongo/db/update/update_object_node.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/update/update_object_node.h | 4 | ||||
-rw-r--r-- | src/mongo/db/update/update_object_node_test.cpp | 254 |
12 files changed, 212 insertions, 605 deletions
diff --git a/src/mongo/db/update/SConscript b/src/mongo/db/update/SConscript index 66b780188b1..be2ed56c9e8 100644 --- a/src/mongo/db/update/SConscript +++ b/src/mongo/db/update/SConscript @@ -80,7 +80,6 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/mongo/db/ops/update', '$BUILD_DIR/mongo/db/update_index_data', - 'array_filter', 'update_common', ], ) @@ -146,21 +145,3 @@ env.CppUnitTest( ], ) -env.Library( - target='array_filter', - source=[ - 'array_filter.cpp', - ], - LIBDEPS=[ - "$BUILD_DIR/mongo/db/matcher/expressions", - ], -) - -env.CppUnitTest( - target='array_filter_test', - source='array_filter_test.cpp', - LIBDEPS=[ - 'array_filter', - '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', - ], -) diff --git a/src/mongo/db/update/array_filter.cpp b/src/mongo/db/update/array_filter.cpp deleted file mode 100644 index e81b8811fed..00000000000 --- a/src/mongo/db/update/array_filter.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (C) 2017 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/update/array_filter.h" - -#include <regex> - -#include "mongo/db/matcher/expression_parser.h" -#include "mongo/db/matcher/extensions_callback_disallow_extensions.h" - -namespace mongo { - -namespace { - -// The array filter must begin with a lowercase letter and contain no special characters. -const std::regex idRegex("^[a-z][a-zA-Z0-9]*$"); - -/** - * Finds the top-level field that 'expr' is over. The must be unique and not the empty string. - */ -StatusWith<StringData> parseId(MatchExpression* expr) { - switch (expr->getCategory()) { - case MatchExpression::MatchCategory::kLeaf: - case MatchExpression::MatchCategory::kArrayMatching: { - auto firstDotPos = expr->path().find('.'); - if (firstDotPos == std::string::npos) { - return expr->path(); - } - return expr->path().substr(0, firstDotPos); - } - case MatchExpression::MatchCategory::kLogical: { - if (expr->numChildren() == 0) { - return Status(ErrorCodes::FailedToParse, - "No top-level field name found in array filter."); - } - - StringData id; - for (size_t i = 0; i < expr->numChildren(); ++i) { - auto statusWithId = parseId(expr->getChild(i)); - if (!statusWithId.isOK()) { - return statusWithId.getStatus(); - } - - if (id == StringData()) { - id = statusWithId.getValue(); - continue; - } - - if (id != statusWithId.getValue()) { - return Status( - ErrorCodes::FailedToParse, - str::stream() - << "Each array filter must use a single top-level field name, found '" - << id - << "' and '" - << statusWithId.getValue() - << "'"); - } - } - return id; - } - case MatchExpression::MatchCategory::kOther: { - return Status(ErrorCodes::FailedToParse, - str::stream() << "Unsupported match expression in array filter"); - } - } - - MONGO_UNREACHABLE; -} - -} // namespace - -// static -StatusWith<std::unique_ptr<ArrayFilter>> ArrayFilter::parse(BSONObj rawArrayFilter, - const CollatorInterface* collator) { - StatusWithMatchExpression statusWithFilter = MatchExpressionParser::parse( - rawArrayFilter, ExtensionsCallbackDisallowExtensions(), collator); - if (!statusWithFilter.isOK()) { - return statusWithFilter.getStatus(); - } - auto filter = std::move(statusWithFilter.getValue()); - - auto statusWithId = parseId(filter.get()); - if (!statusWithId.isOK()) { - return statusWithId.getStatus(); - } - auto id = statusWithId.getValue().toString(); - if (!std::regex_match(id, idRegex)) { - return Status(ErrorCodes::BadValue, - str::stream() - << "The top-level field name in an array filter must be an alphanumeric " - "string beginning with a lowercase letter, found '" - << id - << "'"); - } - - auto arrayFilter = stdx::make_unique<ArrayFilter>(std::move(id), std::move(filter)); - return {std::move(arrayFilter)}; -} - -} // namespace mongo diff --git a/src/mongo/db/update/array_filter.h b/src/mongo/db/update/array_filter.h deleted file mode 100644 index 8fc079fa13d..00000000000 --- a/src/mongo/db/update/array_filter.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (C) 2017 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/db/matcher/expression.h" - -namespace mongo { - -/** - * A filter specifying which array elements an update modifier should apply to. For example, the - * array filter with id "i" and filter {i: 0} specifies that an update {$set: {"a.$[i]"}} should - * only apply to elements of "a" which are equal to 0. - */ -class ArrayFilter { - -public: - /** - * Parses 'rawArrayFilter' to an ArrayFilter. This succeeds if 'rawArrayFilter' is a filter over - * a single top-level field, which begins with a lowercase letter and contains no special - * characters. Otherwise, a non-OK status is returned. Callers must maintain ownership of - * 'rawArrayFilter'. - */ - static StatusWith<std::unique_ptr<ArrayFilter>> parse(BSONObj rawArrayFilter, - const CollatorInterface* collator); - - ArrayFilter(std::string id, std::unique_ptr<MatchExpression> filter) - : _id(std::move(id)), _filter(std::move(filter)) {} - - StringData getId() const { - return _id; - } - - MatchExpression* getFilter() const { - return _filter.get(); - } - -private: - // The top-level field that _filter is over. - const std::string _id; - const std::unique_ptr<MatchExpression> _filter; -}; - -} // namespace mongo diff --git a/src/mongo/db/update/array_filter_test.cpp b/src/mongo/db/update/array_filter_test.cpp deleted file mode 100644 index 2167bb10d93..00000000000 --- a/src/mongo/db/update/array_filter_test.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/** - * Copyright (C) 2017 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/update/array_filter.h" - -#include "mongo/db/json.h" -#include "mongo/db/query/collation/collator_interface_mock.h" -#include "mongo/unittest/unittest.h" - -namespace { - -using namespace mongo; -using unittest::assertGet; - -TEST(ArrayFilterTest, ParseBasic) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{i: 0}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, collator)); - ASSERT_EQ(arrayFilter->getId(), "i"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 0}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 1}"))); -} - -TEST(ArrayFilterTest, ParseDottedField) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'i.a': 0, 'i.b': 1}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, collator)); - ASSERT_EQ(arrayFilter->getId(), "i"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: {a: 0, b: 1}}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: {a: 0, b: 0}}"))); -} - -TEST(ArrayFilterTest, ParseLogicalQuery) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$and: [{i: {$gte: 0}}, {i: {$lte: 0}}]}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, collator)); - ASSERT_EQ(arrayFilter->getId(), "i"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 0}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 1}"))); -} - -TEST(ArrayFilterTest, ParseElemMatch) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{i: {$elemMatch: {a: 0}}}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, collator)); - ASSERT_EQ(arrayFilter->getId(), "i"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: [{a: 0}]}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: [{a: 1}]}"))); -} - -TEST(ArrayFilterTest, ParseCollation) { - CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); - auto rawArrayFilter = fromjson("{i: 'abc'}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, &collator)); - ASSERT_EQ(arrayFilter->getId(), "i"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 'cba'}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{i: 0}"))); -} - -TEST(ArrayFilterTest, ParseIdContainsNumbersAndCapitals) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{iA3: 0}"); - auto arrayFilter = assertGet(ArrayFilter::parse(rawArrayFilter, collator)); - ASSERT_EQ(arrayFilter->getId(), "iA3"); - ASSERT_TRUE(arrayFilter->getFilter()->matchesBSON(fromjson("{'iA3': 0}"))); - ASSERT_FALSE(arrayFilter->getFilter()->matchesBSON(fromjson("{'iA3': 1}"))); -} - -TEST(ArrayFilterTest, BadMatchExpressionFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$and: 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, EmptyMatchExpressionFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, NestedEmptyMatchExpressionFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$or: [{i: 0}, {$and: [{}]}]}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, EmptyFieldNameFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'': 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, EmptyElemMatchFieldNameFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'': {$elemMatch: {a: 0}}}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, EmptyTopLevelFieldNameFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'.i': 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, MultipleTopLevelFieldsFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$and: [{i: 0}, {j: 0}]}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, SpecialCharactersInFieldNameFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'i&': 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, FieldNameStartingWithNumberFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'3i': 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, FieldNameStartingWithCapitalFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{'Ai': 0}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, TextSearchExpressionFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$text: {$search: 'search terms'}}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -TEST(ArrayFilterTest, WhereExpressionFailsToParse) { - const CollatorInterface* collator = nullptr; - auto rawArrayFilter = fromjson("{$where: 'sllep(100)'}"); - auto status = ArrayFilter::parse(rawArrayFilter, collator); - ASSERT_NOT_OK(status.getStatus()); -} - -} // namespace diff --git a/src/mongo/db/update/update_array_node.h b/src/mongo/db/update/update_array_node.h index d99f24518bd..8ccd8d028f8 100644 --- a/src/mongo/db/update/update_array_node.h +++ b/src/mongo/db/update/update_array_node.h @@ -32,7 +32,7 @@ #include <string> #include "mongo/base/clonable_ptr.h" -#include "mongo/db/update/array_filter.h" +#include "mongo/db/matcher/expression_with_placeholder.h" #include "mongo/db/update/update_internal_node.h" #include "mongo/stdx/memory.h" @@ -58,7 +58,8 @@ public: const UpdateArrayNode& rightNode, FieldRef* pathTaken); - UpdateArrayNode(const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters) + UpdateArrayNode( + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters) : UpdateInternalNode(Type::Array), _arrayFilters(arrayFilters) {} std::unique_ptr<UpdateNode> clone() const final { @@ -88,7 +89,7 @@ public: void setChild(std::string field, std::unique_ptr<UpdateNode> child) final; private: - const std::map<StringData, std::unique_ptr<ArrayFilter>>& _arrayFilters; + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& _arrayFilters; std::map<std::string, clonable_ptr<UpdateNode>> _children; // When calling apply() causes us to merge elements of '_children', we store the result of the diff --git a/src/mongo/db/update/update_array_node_test.cpp b/src/mongo/db/update/update_array_node_test.cpp index 99e35fc1b43..a142c04a1f0 100644 --- a/src/mongo/db/update/update_array_node_test.cpp +++ b/src/mongo/db/update/update_array_node_test.cpp @@ -47,8 +47,8 @@ TEST(UpdateArrayNodeTest, ApplyCreatePathFails) { auto update = fromjson("{$set: {'a.b.$[i]': 0}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -92,8 +92,8 @@ TEST(UpdateArrayNodeTest, ApplyToNonArrayFails) { auto update = fromjson("{$set: {'a.$[i]': 0}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -136,8 +136,8 @@ TEST(UpdateArrayNodeTest, UpdateIsAppliedToAllMatchingElements) { auto update = fromjson("{$set: {'a.$[i]': 2}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -184,8 +184,8 @@ DEATH_TEST(UpdateArrayNodeTest, auto update = fromjson("{$set: {'a.$[i].b': 0}}"); auto arrayFilter = fromjson("{'i.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -226,7 +226,7 @@ DEATH_TEST(UpdateArrayNodeTest, TEST(UpdateArrayNodeTest, UpdateForEmptyIdentifierIsAppliedToAllArrayElements) { auto update = fromjson("{$set: {'a.$[]': 1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -273,10 +273,10 @@ TEST(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElement) { auto arrayFilterJ = fromjson("{'j.c': 0}"); auto arrayFilterK = fromjson("{'k.d': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); - arrayFilters["k"] = uassertStatusOK(ArrayFilter::parse(arrayFilterK, collator)); + 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)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -334,9 +334,9 @@ TEST(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsUsingMergedChildren auto arrayFilterI = fromjson("{'i.b': 0}"); auto arrayFilterJ = fromjson("{'j.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -389,10 +389,10 @@ TEST(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsWithoutMergedChildr auto arrayFilterJ = fromjson("{'j.c': 0}"); auto arrayFilterK = fromjson("{'k.d': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); - arrayFilters["k"] = uassertStatusOK(ArrayFilter::parse(arrayFilterK, collator)); + 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)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -448,7 +448,7 @@ TEST(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsWithoutMergedChildr TEST(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementWithEmptyIdentifiers) { auto update = fromjson("{$set: {'a.$[].b': 1, 'a.$[].c': 1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -502,11 +502,11 @@ TEST(UpdateArrayNodeTest, ApplyNestedArrayUpdates) { auto arrayFilterK = fromjson("{'k.x': 0}"); auto arrayFilterL = fromjson("{'l.d': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); - arrayFilters["k"] = uassertStatusOK(ArrayFilter::parse(arrayFilterK, collator)); - arrayFilters["l"] = uassertStatusOK(ArrayFilter::parse(arrayFilterL, collator)); + 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)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -558,9 +558,9 @@ TEST(UpdateArrayNodeTest, ApplyUpdatesWithMergeConflictToArrayElementFails) { auto arrayFilterI = fromjson("{'i': 0}"); auto arrayFilterJ = fromjson("{'j': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -610,9 +610,9 @@ TEST(UpdateArrayNodeTest, ApplyUpdatesWithEmptyIdentifiersWithMergeConflictToArr auto arrayFilterI = fromjson("{'i': 0}"); auto arrayFilterJ = fromjson("{'j': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -664,11 +664,11 @@ TEST(UpdateArrayNodeTest, ApplyNestedArrayUpdatesWithMergeConflictFails) { auto arrayFilterK = fromjson("{'k.c': 0}"); auto arrayFilterL = fromjson("{l: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); - arrayFilters["k"] = uassertStatusOK(ArrayFilter::parse(arrayFilterK, collator)); - arrayFilters["l"] = uassertStatusOK(ArrayFilter::parse(arrayFilterL, collator)); + 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)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -717,8 +717,8 @@ TEST(UpdateArrayNodeTest, NoArrayElementsMatch) { auto update = fromjson("{$set: {'a.$[i]': 1}}"); auto arrayFilter = fromjson("{'i': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -763,8 +763,8 @@ TEST(UpdateArrayNodeTest, UpdatesToAllArrayElementsAreNoops) { auto update = fromjson("{$set: {'a.$[i]': 1}}"); auto arrayFilter = fromjson("{'i': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -809,8 +809,8 @@ TEST(UpdateArrayNodeTest, NoArrayElementAffectsIndexes) { auto update = fromjson("{$set: {'a.$[i].b': 0}}"); auto arrayFilter = fromjson("{'i.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -855,8 +855,8 @@ TEST(UpdateArrayNodeTest, WhenOneElementIsMatchedLogElementUpdateDirectly) { auto update = fromjson("{$set: {'a.$[i].b': 0}}"); auto arrayFilter = fromjson("{'i.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -901,8 +901,8 @@ TEST(UpdateArrayNodeTest, WhenOneElementIsModifiedLogElement) { auto update = fromjson("{$set: {'a.$[i].b': 0}}"); auto arrayFilter = fromjson("{'i.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -946,7 +946,7 @@ TEST(UpdateArrayNodeTest, WhenOneElementIsModifiedLogElement) { TEST(UpdateArrayNodeTest, ArrayUpdateOnEmptyArrayIsANoop) { auto update = fromjson("{$set: {'a.$[]': 0}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -991,8 +991,8 @@ TEST(UpdateArrayNodeTest, ApplyPositionalInsideArrayUpdate) { auto update = fromjson("{$set: {'a.$[i].b.$': 1}}"); auto arrayFilter = fromjson("{'i.c': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1037,8 +1037,8 @@ TEST(UpdateArrayNodeTest, ApplyArrayUpdateFromReplication) { auto update = fromjson("{$set: {'a.$[i].b': 1}}"); auto arrayFilter = fromjson("{'i': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1083,8 +1083,8 @@ TEST(UpdateArrayNodeTest, ApplyArrayUpdateNotFromReplication) { auto update = fromjson("{$set: {'a.$[i].b': 1}}"); auto arrayFilter = fromjson("{'i': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1127,8 +1127,8 @@ TEST(UpdateArrayNodeTest, ApplyArrayUpdateWithoutLogBuilderOrIndexData) { auto update = fromjson("{$set: {'a.$[i]': 1}}"); auto arrayFilter = fromjson("{'i': 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp index 7fc363af7db..b094dcef6f9 100644 --- a/src/mongo/db/update/update_driver.cpp +++ b/src/mongo/db/update/update_driver.cpp @@ -90,7 +90,7 @@ StatusWith<bool> parseUpdateExpression( BSONObj updateExpr, UpdateObjectNode* root, const CollatorInterface* collator, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters) { + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters) { bool positional = false; std::set<std::string> foundIdentifiers; for (auto&& mod : updateExpr) { @@ -144,9 +144,10 @@ UpdateDriver::~UpdateDriver() { clear(); } -Status UpdateDriver::parse(const BSONObj& updateExpr, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters, - const bool multi) { +Status UpdateDriver::parse( + const BSONObj& updateExpr, + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters, + const bool multi) { clear(); // Check if the update expression is a full object replacement. diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h index 06e9d0a4f91..c188ae62960 100644 --- a/src/mongo/db/update/update_driver.h +++ b/src/mongo/db/update/update_driver.h @@ -64,9 +64,10 @@ public: * 'arrayFilters' is non-empty. Uasserts or returns a non-ok status if 'updateExpr' fails to * parse. */ - Status parse(const BSONObj& updateExpr, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters, - const bool multi = false); + Status parse( + const BSONObj& updateExpr, + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters, + const bool multi = false); /** * Fills in document with any fields in the query which are valid. diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp index e7db2df426e..f37074ce24b 100644 --- a/src/mongo/db/update/update_driver_test.cpp +++ b/src/mongo/db/update/update_driver_test.cpp @@ -53,7 +53,7 @@ using mongoutils::str::stream; TEST(Parse, Normal) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters)); ASSERT_EQUALS(driver.numMods(), 1U); ASSERT_FALSE(driver.isDocReplacement()); @@ -62,7 +62,7 @@ TEST(Parse, Normal) { TEST(Parse, MultiMods) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters)); ASSERT_EQUALS(driver.numMods(), 2U); ASSERT_FALSE(driver.isDocReplacement()); @@ -71,7 +71,7 @@ TEST(Parse, MultiMods) { TEST(Parse, MixingMods) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters)); ASSERT_EQUALS(driver.numMods(), 2U); ASSERT_FALSE(driver.isDocReplacement()); @@ -80,7 +80,7 @@ TEST(Parse, MixingMods) { TEST(Parse, ObjectReplacment) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters)); ASSERT_TRUE(driver.isDocReplacement()); } @@ -88,7 +88,7 @@ TEST(Parse, ObjectReplacment) { TEST(Parse, EmptyMod) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_THROWS_CODE_AND_WHAT( driver.parse(fromjson("{$set:{}}"), arrayFilters).transitional_ignore(), UserException, @@ -99,7 +99,7 @@ TEST(Parse, EmptyMod) { TEST(Parse, WrongMod) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_THROWS_CODE_AND_WHAT( driver.parse(fromjson("{$xyz:{a:1}}"), arrayFilters).transitional_ignore(), UserException, @@ -110,7 +110,7 @@ TEST(Parse, WrongMod) { TEST(Parse, WrongType) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_THROWS_CODE_AND_WHAT( driver.parse(fromjson("{$set:[{a:1}]}"), arrayFilters).transitional_ignore(), UserException, @@ -122,7 +122,7 @@ TEST(Parse, WrongType) { TEST(Parse, ModsWithLaterObjReplacement) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_THROWS_CODE_AND_WHAT( driver.parse(fromjson("{$set:{a:1}, obj: \"obj replacement\"}"), arrayFilters) .transitional_ignore(), @@ -134,7 +134,7 @@ TEST(Parse, ModsWithLaterObjReplacement) { TEST(Parse, PushAll) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{$pushAll:{a:[1,2,3]}}"), arrayFilters)); ASSERT_EQUALS(driver.numMods(), 1U); ASSERT_FALSE(driver.isDocReplacement()); @@ -143,7 +143,7 @@ TEST(Parse, PushAll) { TEST(Parse, SetOnInsert) { UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters)); ASSERT_EQUALS(driver.numMods(), 1U); ASSERT_FALSE(driver.isDocReplacement()); @@ -154,7 +154,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) { BSONObj updateDocument = fromjson("{$max: {a: 'abd'}}"); UpdateDriver::Options opts; UpdateDriver driver(opts); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_OK(driver.parse(updateDocument, arrayFilters)); ASSERT_EQUALS(driver.numMods(), 1U); @@ -214,7 +214,7 @@ public: private: QueryTestServiceContext _serviceContext; ServiceContext::UniqueOperationContext _opCtx; - std::map<StringData, std::unique_ptr<ArrayFilter>> _arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> _arrayFilters; std::unique_ptr<UpdateDriver> _driverOps; std::unique_ptr<UpdateDriver> _driverRepl; Document _doc; diff --git a/src/mongo/db/update/update_object_node.cpp b/src/mongo/db/update/update_object_node.cpp index fa274085ea8..25c51dc32a2 100644 --- a/src/mongo/db/update/update_object_node.cpp +++ b/src/mongo/db/update/update_object_node.cpp @@ -51,7 +51,7 @@ StatusWith<std::string> parseArrayFilterIdentifier( StringData field, size_t position, const FieldRef& fieldRef, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters, + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters, std::set<std::string>& foundIdentifiers) { dassert(fieldchecker::isArrayFilterIdentifier(field)); @@ -197,7 +197,7 @@ StatusWith<bool> UpdateObjectNode::parseAndMerge( modifiertable::ModifierType type, BSONElement modExpr, const CollatorInterface* collator, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters, + const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters, std::set<std::string>& foundIdentifiers) { FieldRef fieldRef; if (type != modifiertable::ModifierType::MOD_RENAME) { diff --git a/src/mongo/db/update/update_object_node.h b/src/mongo/db/update/update_object_node.h index d43fc09026e..07ed5b77dfd 100644 --- a/src/mongo/db/update/update_object_node.h +++ b/src/mongo/db/update/update_object_node.h @@ -33,7 +33,7 @@ #include "mongo/base/clonable_ptr.h" #include "mongo/bson/bsonelement.h" -#include "mongo/db/update/array_filter.h" +#include "mongo/db/matcher/expression_with_placeholder.h" #include "mongo/db/update/modifier_table.h" #include "mongo/db/update/update_internal_node.h" #include "mongo/stdx/memory.h" @@ -61,7 +61,7 @@ public: modifiertable::ModifierType type, BSONElement modExpr, const CollatorInterface* collator, - const std::map<StringData, std::unique_ptr<ArrayFilter>>& arrayFilters, + 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 b4b4a8561f3..3257380011e 100644 --- a/src/mongo/db/update/update_object_node_test.cpp +++ b/src/mongo/db/update/update_object_node_test.cpp @@ -49,7 +49,7 @@ using mongo::mutablebson::Element; TEST(UpdateObjectNodeTest, InvalidPathFailsToParse) { auto update = fromjson("{$set: {'': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -66,7 +66,7 @@ TEST(UpdateObjectNodeTest, InvalidPathFailsToParse) { TEST(UpdateObjectNodeTest, ValidIncPathParsesSuccessfully) { auto update = fromjson("{$inc: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -80,7 +80,7 @@ TEST(UpdateObjectNodeTest, ValidIncPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidMulPathParsesSuccessfully) { auto update = fromjson("{$mul: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -94,7 +94,7 @@ TEST(UpdateObjectNodeTest, ValidMulPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidRenamePathParsesSuccessfully) { auto update = fromjson("{$rename: {'a.b': 'c.d'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -122,7 +122,7 @@ TEST(UpdateObjectNodeTest, ValidRenamePathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidSetPathParsesSuccessfully) { auto update = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -136,7 +136,7 @@ TEST(UpdateObjectNodeTest, ValidSetPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidUnsetPathParsesSuccessfully) { auto update = fromjson("{$unset: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -150,7 +150,7 @@ TEST(UpdateObjectNodeTest, ValidUnsetPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidAddToSetPathParsesSuccessfully) { auto update = fromjson("{$addToSet: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -164,7 +164,7 @@ TEST(UpdateObjectNodeTest, ValidAddToSetPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidPopPathParsesSuccessfully) { auto update = fromjson("{$pop: {'a.b': 1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -178,7 +178,7 @@ TEST(UpdateObjectNodeTest, ValidPopPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidMaxPathParsesSuccessfully) { auto update = fromjson("{$max: {'a.b': 1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -192,7 +192,7 @@ TEST(UpdateObjectNodeTest, ValidMaxPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidMinPathParsesSuccessfully) { auto update = fromjson("{$min: {'a.b': 1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -206,7 +206,7 @@ TEST(UpdateObjectNodeTest, ValidMinPathParsesSuccessfully) { TEST(UpdateObjectNodeTest, ValidCurrentDatePathParsesSuccessfully) { auto update = fromjson("{$currentDate: {'a.b': true}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -220,7 +220,7 @@ TEST(UpdateObjectNodeTest, ValidCurrentDatePathParsesSuccessfully) { TEST(UpdateObjectNodeTest, MultiplePositionalElementsFailToParse) { auto update = fromjson("{$set: {'a.$.b.$': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -238,7 +238,7 @@ TEST(UpdateObjectNodeTest, MultiplePositionalElementsFailToParse) { TEST(UpdateObjectNodeTest, ParsingSetsPositionalTrue) { auto update = fromjson("{$set: {'a.$.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -254,7 +254,7 @@ TEST(UpdateObjectNodeTest, ParsingSetsPositionalTrue) { TEST(UpdateObjectNodeTest, ParsingSetsPositionalFalse) { auto update = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -270,7 +270,7 @@ TEST(UpdateObjectNodeTest, ParsingSetsPositionalFalse) { TEST(UpdateObjectNodeTest, PositionalElementFirstPositionFailsToParse) { auto update = fromjson("{$set: {'$': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -289,7 +289,7 @@ TEST(UpdateObjectNodeTest, PositionalElementFirstPositionFailsToParse) { TEST(UpdateObjectNodeTest, PushFailsToParse) { auto update = fromjson("{$push: {a: 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -306,7 +306,7 @@ TEST(UpdateObjectNodeTest, PushFailsToParse) { TEST(UpdateObjectNodeTest, TwoModifiersOnSameFieldFailToParse) { auto update = fromjson("{$set: {a: 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -329,7 +329,7 @@ TEST(UpdateObjectNodeTest, TwoModifiersOnSameFieldFailToParse) { TEST(UpdateObjectNodeTest, TwoModifiersOnDifferentFieldsParseSuccessfully) { auto update = fromjson("{$set: {a: 5, b: 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -349,7 +349,7 @@ TEST(UpdateObjectNodeTest, TwoModifiersOnDifferentFieldsParseSuccessfully) { TEST(UpdateObjectNodeTest, TwoModifiersWithSameDottedPathFailToParse) { auto update = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -373,7 +373,7 @@ TEST(UpdateObjectNodeTest, TwoModifiersWithSameDottedPathFailToParse) { TEST(UpdateObjectNodeTest, FirstModifierPrefixOfSecondFailToParse) { auto update = fromjson("{$set: {a: 5, 'a.b': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -397,7 +397,7 @@ TEST(UpdateObjectNodeTest, FirstModifierPrefixOfSecondFailToParse) { TEST(UpdateObjectNodeTest, FirstModifierDottedPrefixOfSecondFailsToParse) { auto update = fromjson("{$set: {'a.b': 5, 'a.b.c': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -421,7 +421,7 @@ TEST(UpdateObjectNodeTest, FirstModifierDottedPrefixOfSecondFailsToParse) { TEST(UpdateObjectNodeTest, SecondModifierPrefixOfFirstFailsToParse) { auto update = fromjson("{$set: {'a.b': 5, a: 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -444,7 +444,7 @@ TEST(UpdateObjectNodeTest, SecondModifierPrefixOfFirstFailsToParse) { TEST(UpdateObjectNodeTest, SecondModifierDottedPrefixOfFirstFailsToParse) { auto update = fromjson("{$set: {'a.b.c': 5, 'a.b': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -468,7 +468,7 @@ TEST(UpdateObjectNodeTest, SecondModifierDottedPrefixOfFirstFailsToParse) { TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixParseSuccessfully) { auto update = fromjson("{$set: {'a.b': 5, 'a.c': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -488,7 +488,7 @@ TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixParseSuccessfully) { TEST(UpdateObjectNodeTest, ModifiersWithCommonDottedPrefixParseSuccessfully) { auto update = fromjson("{$set: {'a.b.c': 5, 'a.b.d': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -508,7 +508,7 @@ TEST(UpdateObjectNodeTest, ModifiersWithCommonDottedPrefixParseSuccessfully) { TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixDottedSuffixParseSuccessfully) { auto update = fromjson("{$set: {'a.b.c': 5, 'a.d.e': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -528,7 +528,7 @@ TEST(UpdateObjectNodeTest, ModifiersWithCommonPrefixDottedSuffixParseSuccessfull TEST(UpdateObjectNodeTest, TwoModifiersOnSamePositionalFieldFailToParse) { auto update = fromjson("{$set: {'a.$': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -552,7 +552,7 @@ TEST(UpdateObjectNodeTest, TwoModifiersOnSamePositionalFieldFailToParse) { TEST(UpdateObjectNodeTest, PositionalFieldsWithDifferentPrefixesParseSuccessfully) { auto update = fromjson("{$set: {'a.$': 5, 'b.$': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -572,7 +572,7 @@ TEST(UpdateObjectNodeTest, PositionalFieldsWithDifferentPrefixesParseSuccessfull TEST(UpdateObjectNodeTest, PositionalAndNonpositionalFieldWithCommonPrefixParseSuccessfully) { auto update = fromjson("{$set: {'a.$': 5, 'a.0': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -592,7 +592,7 @@ TEST(UpdateObjectNodeTest, PositionalAndNonpositionalFieldWithCommonPrefixParseS TEST(UpdateObjectNodeTest, TwoModifiersWithSamePositionalDottedPathFailToParse) { auto update = fromjson("{$set: {'a.$.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -616,7 +616,7 @@ TEST(UpdateObjectNodeTest, TwoModifiersWithSamePositionalDottedPathFailToParse) TEST(UpdateObjectNodeTest, FirstModifierPositionalPrefixOfSecondFailsToParse) { auto update = fromjson("{$set: {'a.$': 5, 'a.$.b': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -640,7 +640,7 @@ TEST(UpdateObjectNodeTest, FirstModifierPositionalPrefixOfSecondFailsToParse) { TEST(UpdateObjectNodeTest, SecondModifierPositionalPrefixOfFirstFailsToParse) { auto update = fromjson("{$set: {'a.$.b': 5, 'a.$': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -664,7 +664,7 @@ TEST(UpdateObjectNodeTest, SecondModifierPositionalPrefixOfFirstFailsToParse) { TEST(UpdateObjectNodeTest, FirstModifierFieldPrefixOfSecondParsesSuccessfully) { auto update = fromjson("{$set: {'a': 5, 'ab': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -684,7 +684,7 @@ TEST(UpdateObjectNodeTest, FirstModifierFieldPrefixOfSecondParsesSuccessfully) { TEST(UpdateObjectNodeTest, SecondModifierFieldPrefixOfSecondParsesSuccessfully) { auto update = fromjson("{$set: {'ab': 5, 'a': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -704,7 +704,7 @@ TEST(UpdateObjectNodeTest, SecondModifierFieldPrefixOfSecondParsesSuccessfully) TEST(UpdateObjectNodeTest, IdentifierWithoutArrayFilterFailsToParse) { auto update = fromjson("{$set: {'a.$[i]': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -722,7 +722,7 @@ TEST(UpdateObjectNodeTest, IdentifierWithoutArrayFilterFailsToParse) { TEST(UpdateObjectNodeTest, IdentifierInMiddleOfPathWithoutArrayFilterFailsToParse) { auto update = fromjson("{$set: {'a.$[i].b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -740,7 +740,7 @@ TEST(UpdateObjectNodeTest, IdentifierInMiddleOfPathWithoutArrayFilterFailsToPars TEST(UpdateObjectNodeTest, EmptyIdentifierParsesSuccessfully) { auto update = fromjson("{$set: {'a.$[]': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -755,7 +755,7 @@ TEST(UpdateObjectNodeTest, EmptyIdentifierParsesSuccessfully) { TEST(UpdateObjectNodeTest, EmptyIdentifierInMiddleOfPathParsesSuccessfully) { auto update = fromjson("{$set: {'a.$[].b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -771,8 +771,8 @@ TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterParsesSuccessfully) { auto update = fromjson("{$set: {'a.$[i]': 5}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -789,8 +789,8 @@ TEST(UpdateObjectNodeTest, IdentifierWithArrayFilterInMiddleOfPathParsesSuccessf auto update = fromjson("{$set: {'a.$[i].b': 5}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -807,8 +807,8 @@ TEST(UpdateObjectNodeTest, IdentifierInFirstPositionFailsToParse) { auto update = fromjson("{$set: {'$[i]': 5}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -828,8 +828,8 @@ TEST(UpdateObjectNodeTest, IdentifierInFirstPositionWithSuffixFailsToParse) { auto update = fromjson("{$set: {'$[i].a': 5}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -849,8 +849,8 @@ TEST(UpdateObjectNodeTest, CreateObjectNodeInSamePositionAsArrayNodeFailsToParse auto update = fromjson("{$set: {'a.$[i]': 5, 'a.0': 6}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -877,8 +877,8 @@ TEST(UpdateObjectNodeTest, CreateArrayNodeInSamePositionAsObjectNodeFailsToParse auto update = fromjson("{$set: {'a.0': 5, 'a.$[i]': 6}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -903,8 +903,8 @@ TEST(UpdateObjectNodeTest, CreateLeafNodeInSamePositionAsArrayNodeFailsToParse) auto update = fromjson("{$set: {'a.$[i]': 5, a: 6}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -930,8 +930,8 @@ TEST(UpdateObjectNodeTest, CreateArrayNodeInSamePositionAsLeafNodeFailsToParse) auto update = fromjson("{$set: {a: 5, 'a.$[i]': 6}}"); auto arrayFilter = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -957,9 +957,9 @@ TEST(UpdateObjectNodeTest, CreateTwoChildrenOfArrayNodeParsesSuccessfully) { auto arrayFilterI = fromjson("{i: 0}"); auto arrayFilterJ = fromjson("{j: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -986,8 +986,8 @@ TEST(UpdateObjectNodeTest, ConflictAtArrayNodeChildFailsToParse) { auto update2 = fromjson("{$set: {'a.$[i]': 6}}"); auto arrayFilterI = fromjson("{i: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1014,8 +1014,8 @@ 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; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1043,9 +1043,9 @@ TEST(UpdateObjectNodeTest, NoConflictDueToDifferentArrayNodeChildrenParsesSucces auto arrayFilterI = fromjson("{i: 0}"); auto arrayFilterJ = fromjson("{j: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1072,9 +1072,9 @@ TEST(UpdateObjectNodeTest, MultipleArrayNodesAlongPathParsesSuccessfully) { auto arrayFilterI = fromjson("{i: 0}"); auto arrayFilterJ = fromjson("{j: 0}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1111,7 +1111,7 @@ TEST(UpdateObjectNodeTest, DistinctFieldsMergeCorrectly) { auto setUpdate2 = fromjson("{$set: {'ab': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1141,7 +1141,7 @@ TEST(UpdateObjectNodeTest, NestedMergeSucceeds) { auto setUpdate2 = fromjson("{$set: {'a.d': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1177,7 +1177,7 @@ TEST(UpdateObjectNodeTest, DoublyNestedMergeSucceeds) { auto setUpdate2 = fromjson("{$set: {'a.b.d': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1219,7 +1219,7 @@ TEST(UpdateObjectNodeTest, FieldAndPositionalMergeCorrectly) { auto setUpdate2 = fromjson("{$set: {'a.$': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1256,7 +1256,7 @@ TEST(UpdateObjectNodeTest, MergeThroughPositionalSucceeds) { auto setUpdate2 = fromjson("{$set: {'a.$.c': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1298,7 +1298,7 @@ TEST(UpdateObjectNodeTest, TopLevelConflictFails) { auto setUpdate2 = fromjson("{$set: {'a': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1327,7 +1327,7 @@ TEST(UpdateObjectNodeTest, NestedConflictFails) { auto setUpdate2 = fromjson("{$set: {'a.b': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1356,7 +1356,7 @@ TEST(UpdateObjectNodeTest, LeftPrefixMergeFails) { auto setUpdate2 = fromjson("{$set: {'a.b.c': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1385,7 +1385,7 @@ TEST(UpdateObjectNodeTest, RightPrefixMergeFails) { auto setUpdate2 = fromjson("{$set: {'a.b': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1414,7 +1414,7 @@ TEST(UpdateObjectNodeTest, LeftPrefixMergeThroughPositionalFails) { auto setUpdate2 = fromjson("{$set: {'a.$.c.d': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1443,7 +1443,7 @@ TEST(UpdateObjectNodeTest, RightPrefixMergeThroughPositionalFails) { auto setUpdate2 = fromjson("{$set: {'a.$.c': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1472,7 +1472,7 @@ TEST(UpdateObjectNodeTest, MergeWithConflictingPositionalFails) { auto setUpdate2 = fromjson("{$set: {'a.$': 6}}"); FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1504,11 +1504,11 @@ DEATH_TEST(UpdateObjectNodeTest, FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; auto arrayFilterI = fromjson("{i: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters1; - arrayFilters1["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters1; + arrayFilters1["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); auto arrayFilterJ = fromjson("{j: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters2; - arrayFilters2["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters2; + arrayFilters2["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1533,8 +1533,8 @@ TEST(UpdateObjectNodeTest, MergingArrayNodeWithObjectNodeFails) { FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; auto arrayFilter = fromjson("{i: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1564,8 +1564,8 @@ TEST(UpdateObjectNodeTest, MergingArrayNodeWithLeafNodeFails) { FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; auto arrayFilter = fromjson("{i: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1596,9 +1596,9 @@ TEST(UpdateObjectNodeTest, MergingTwoArrayNodesSucceeds) { const CollatorInterface* collator = nullptr; auto arrayFilterI = fromjson("{i: 0}"); auto arrayFilterJ = fromjson("{j: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilterI, collator)); - arrayFilters["j"] = uassertStatusOK(ArrayFilter::parse(arrayFilterJ, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterI, collator)); + arrayFilters["j"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilterJ, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1635,8 +1635,8 @@ TEST(UpdateObjectNodeTest, MergeConflictThroughArrayNodesFails) { FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; auto arrayFilter = fromjson("{i: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1666,8 +1666,8 @@ TEST(UpdateObjectNodeTest, NoMergeConflictThroughArrayNodesSucceeds) { FieldRef fakeFieldRef("root"); const CollatorInterface* collator = nullptr; auto arrayFilter = fromjson("{i: 0}"); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; - arrayFilters["i"] = uassertStatusOK(ArrayFilter::parse(arrayFilter, collator)); + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; + arrayFilters["i"] = uassertStatusOK(ExpressionWithPlaceholder::parse(arrayFilter, collator)); std::set<std::string> foundIdentifiers; UpdateObjectNode setRoot1, setRoot2; ASSERT_OK(UpdateObjectNode::parseAndMerge(&setRoot1, @@ -1707,7 +1707,7 @@ TEST(UpdateObjectNodeTest, NoMergeConflictThroughArrayNodesSucceeds) { TEST(UpdateObjectNodeTest, ApplyCreateField) { auto setUpdate = fromjson("{$set: {b: 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1751,7 +1751,7 @@ TEST(UpdateObjectNodeTest, ApplyCreateField) { TEST(UpdateObjectNodeTest, ApplyExistingField) { auto setUpdate = fromjson("{$set: {a: 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1795,7 +1795,7 @@ TEST(UpdateObjectNodeTest, ApplyExistingField) { TEST(UpdateObjectNodeTest, ApplyExistingAndNonexistingFields) { auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7, d: 8}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1857,7 +1857,7 @@ TEST(UpdateObjectNodeTest, ApplyExistingAndNonexistingFields) { TEST(UpdateObjectNodeTest, ApplyExistingNestedPaths) { auto setUpdate = fromjson("{$set: {'a.b': 6, 'a.c': 7, 'b.d': 8, 'b.e': 9}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1920,7 +1920,7 @@ TEST(UpdateObjectNodeTest, ApplyExistingNestedPaths) { TEST(UpdateObjectNodeTest, ApplyCreateNestedPaths) { auto setUpdate = fromjson("{$set: {'a.b': 6, 'a.c': 7, 'b.d': 8, 'b.e': 9}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -1983,7 +1983,7 @@ TEST(UpdateObjectNodeTest, ApplyCreateNestedPaths) { TEST(UpdateObjectNodeTest, ApplyCreateDeeplyNestedPaths) { auto setUpdate = fromjson("{$set: {'a.b.c.d': 6, 'a.b.c.e': 7, 'a.f': 8}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2040,7 +2040,7 @@ TEST(UpdateObjectNodeTest, ApplyCreateDeeplyNestedPaths) { TEST(UpdateObjectNodeTest, ChildrenShouldBeAppliedInAlphabeticalOrder) { auto setUpdate = fromjson("{$set: {a: 5, d: 6, c: 7, b: 8, z: 9}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2108,7 +2108,7 @@ TEST(UpdateObjectNodeTest, ChildrenShouldBeAppliedInAlphabeticalOrder) { TEST(UpdateObjectNodeTest, CollatorShouldNotAffectUpdateOrder) { auto setUpdate = fromjson("{$set: {abc: 5, cba: 6}}"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2158,7 +2158,7 @@ TEST(UpdateObjectNodeTest, CollatorShouldNotAffectUpdateOrder) { TEST(UpdateObjectNodeTest, ApplyNoop) { auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2216,7 +2216,7 @@ TEST(UpdateObjectNodeTest, ApplyNoop) { TEST(UpdateObjectNodeTest, ApplySomeChildrenNoops) { auto setUpdate = fromjson("{$set: {a: 5, b: 6, c: 7}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2274,7 +2274,7 @@ TEST(UpdateObjectNodeTest, ApplySomeChildrenNoops) { TEST(UpdateObjectNodeTest, ApplyBlockingElement) { auto setUpdate = fromjson("{$set: {'a.b': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2316,7 +2316,7 @@ TEST(UpdateObjectNodeTest, ApplyBlockingElement) { TEST(UpdateObjectNodeTest, ApplyBlockingElementFromReplication) { auto setUpdate = fromjson("{$set: {'a.b': 5, b: 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2366,7 +2366,7 @@ TEST(UpdateObjectNodeTest, ApplyBlockingElementFromReplication) { TEST(UpdateObjectNodeTest, ApplyPositionalMissingMatchedField) { auto setUpdate = fromjson("{$set: {'a.$': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2409,7 +2409,7 @@ TEST(UpdateObjectNodeTest, ApplyPositionalMissingMatchedField) { TEST(UpdateObjectNodeTest, ApplyMergePositionalChild) { auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2459,7 +2459,7 @@ TEST(UpdateObjectNodeTest, ApplyMergePositionalChild) { TEST(UpdateObjectNodeTest, ApplyOrderMergedPositionalChild) { auto setUpdate = fromjson("{$set: {'a.2': 5, 'a.1.b': 6, 'a.0': 7, 'a.$.c': 8}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2522,7 +2522,7 @@ TEST(UpdateObjectNodeTest, ApplyOrderMergedPositionalChild) { TEST(UpdateObjectNodeTest, ApplyMergeConflictWithPositionalChild) { auto setUpdate = fromjson("{$set: {'a.0': 5, 'a.$': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2570,7 +2570,7 @@ TEST(UpdateObjectNodeTest, ApplyMergeConflictWithPositionalChild) { TEST(UpdateObjectNodeTest, ApplyDoNotMergePositionalChild) { auto setUpdate = fromjson("{$set: {'a.0': 5, 'a.2': 6, 'a.$': 7}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2626,7 +2626,7 @@ TEST(UpdateObjectNodeTest, ApplyDoNotMergePositionalChild) { TEST(UpdateObjectNodeTest, ApplyPositionalChildLast) { auto setUpdate = fromjson("{$set: {'a.$': 5, 'a.0': 6, 'a.1': 7}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2682,7 +2682,7 @@ TEST(UpdateObjectNodeTest, ApplyPositionalChildLast) { TEST(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) { auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2752,7 +2752,7 @@ TEST(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) { TEST(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) { auto setUpdate = fromjson("{$set: {'a.0.b': 5, 'a.$.c': 6, 'a.1.d': 7}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2835,7 +2835,7 @@ TEST(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) { TEST(UpdateObjectNodeTest, ApplyToArrayByIndexWithLeadingZero) { auto setUpdate = fromjson("{$set: {'a.02': 2}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2885,7 +2885,7 @@ TEST(UpdateObjectNodeTest, ApplyToArrayByIndexWithLeadingZero) { TEST(UpdateObjectNodeTest, ApplyMultipleArrayUpdates) { auto setUpdate = fromjson("{$set: {'a.2': 2, 'a.10': 10}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2937,7 +2937,7 @@ TEST(UpdateObjectNodeTest, ApplyMultipleArrayUpdates) { TEST(UpdateObjectNodeTest, ApplyUpdateToNonViablePathInArray) { auto setUpdate = fromjson("{$set: {'a.b': 3}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -2979,7 +2979,7 @@ TEST(UpdateObjectNodeTest, ApplyUpdateToNonViablePathInArray) { TEST(UpdateObjectNodeTest, SetAndPopModifiersWithCommonPrefixApplySuccessfully) { auto update = fromjson("{$set: {'a.b': 5}, $pop: {'a.c': -1}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -3027,7 +3027,7 @@ TEST(UpdateObjectNodeTest, SetAndPopModifiersWithCommonPrefixApplySuccessfully) TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) { const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; { @@ -3094,7 +3094,7 @@ TEST(ParseRenameTest, RenameToStringWithEmbeddedNullFails) { TEST(ParseRenameTest, RenameToNonUpdatablePathFails) { auto update = fromjson("{$rename: {'a': 'b.'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3112,7 +3112,7 @@ TEST(ParseRenameTest, RenameToNonUpdatablePathFails) { TEST(ParseRenameTest, RenameFromNonUpdatablePathFails) { auto update = fromjson("{$rename: {'.a': 'b'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3130,7 +3130,7 @@ TEST(ParseRenameTest, RenameFromNonUpdatablePathFails) { TEST(ParseRenameTest, RenameToNonStringPathFails) { auto update = fromjson("{$rename: {'a': 5}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3154,7 +3154,7 @@ TEST(ParseRenameTest, RenameToNonStringPathFails) { TEST(ParseRenameTest, RenameWithSameNameFails) { auto update = fromjson("{$rename: {'a': 'a'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3172,7 +3172,7 @@ TEST(ParseRenameTest, RenameWithSameNameFails) { TEST(ParseRenameTest, RenameUpwardFails) { auto update = fromjson("{$rename: {'b.a': 'b'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3190,7 +3190,7 @@ TEST(ParseRenameTest, RenameUpwardFails) { TEST(ParseRenameTest, RenameDownwardFails) { auto update = fromjson("{$rename: {'b': 'b.a'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; auto result = UpdateObjectNode::parseAndMerge(&root, @@ -3208,7 +3208,7 @@ TEST(ParseRenameTest, RenameDownwardFails) { TEST(ParseRenameTest, ConflictWithRenameSourceFailsToParse) { auto update = fromjson("{$set: {a: 5}, $rename: {a: 'b'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, @@ -3231,7 +3231,7 @@ TEST(ParseRenameTest, ConflictWithRenameSourceFailsToParse) { TEST(ParseRenameTest, ConflictWithRenameDestinationFailsToParse) { auto update = fromjson("{$set: {b: 5}, $rename: {a: 'b'}}"); const CollatorInterface* collator = nullptr; - std::map<StringData, std::unique_ptr<ArrayFilter>> arrayFilters; + std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; std::set<std::string> foundIdentifiers; UpdateObjectNode root; ASSERT_OK(UpdateObjectNode::parseAndMerge(&root, |