summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorMinji <minjikim0202@gmail.com>2018-06-18 15:03:24 -0400
committerMinji <minjikim0202@gmail.com>2018-06-29 13:33:23 -0400
commit77d35b732b4aa312ba7dd3505dd90fbfe9b6753e (patch)
treeb9fcd89b7ebd001aaf9c37398a7014ffdca0362e /src/mongo/db
parenta3f0ad233bab0f49ae19bbc14468c4b600ec794e (diff)
downloadmongo-77d35b732b4aa312ba7dd3505dd90fbfe9b6753e.tar.gz
SERVER-32348 Make UpdateDriver::parse() throw an exception instead of returning error Status
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp6
-rw-r--r--src/mongo/db/auth/role_graph_update.cpp4
-rw-r--r--src/mongo/db/ops/parsed_update.cpp8
-rw-r--r--src/mongo/db/ops/parsed_update.h2
-rw-r--r--src/mongo/db/ops/update.cpp11
-rw-r--r--src/mongo/db/update/update_driver.cpp22
-rw-r--r--src/mongo/db/update/update_driver.h11
-rw-r--r--src/mongo/db/update/update_driver_test.cpp50
8 files changed, 51 insertions, 63 deletions
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.cpp b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
index d755d61c556..62c8c9fae74 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -186,12 +186,10 @@ Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx,
boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
UpdateDriver driver(std::move(expCtx));
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- Status status = driver.parse(updatePattern, arrayFilters);
- if (!status.isOK())
- return status;
+ driver.parse(updatePattern, arrayFilters);
BSONObjCollection::iterator iter;
- status = _findOneIter(opCtx, collectionName, query, &iter);
+ Status status = _findOneIter(opCtx, collectionName, query, &iter);
mmb::Document document;
if (status.isOK()) {
document.reset(*iter, mmb::Document::kInPlaceDisabled);
diff --git a/src/mongo/db/auth/role_graph_update.cpp b/src/mongo/db/auth/role_graph_update.cpp
index 89a67b44638..16f4f1cb566 100644
--- a/src/mongo/db/auth/role_graph_update.cpp
+++ b/src/mongo/db/auth/role_graph_update.cpp
@@ -208,9 +208,7 @@ Status handleOplogUpdate(OperationContext* opCtx,
// Oplog updates do not have array filters.
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- status = driver.parse(updatePattern, arrayFilters);
- if (!status.isOK())
- return status;
+ driver.parse(updatePattern, arrayFilters);
mutablebson::Document roleDocument;
status = RoleGraph::getBSONForRole(roleGraph, roleToUpdate, roleDocument.root());
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index d7a31d0b936..f3da8cb18c3 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -72,9 +72,7 @@ Status ParsedUpdate::parseRequest() {
// may determine whether or not we need to produce a CanonicalQuery at all. For example, if
// the update involves the positional-dollar operator, we must have a CanonicalQuery even if
// it isn't required for query execution.
- status = parseUpdate();
- if (!status.isOK())
- return status;
+ parseUpdate();
status = parseQuery();
if (!status.isOK())
return status;
@@ -139,12 +137,12 @@ Status ParsedUpdate::parseQueryToCQ() {
return statusWithCQ.getStatus();
}
-Status ParsedUpdate::parseUpdate() {
+void ParsedUpdate::parseUpdate() {
_driver.setCollator(_collator.get());
_driver.setLogOp(true);
_driver.setFromOplogApplication(_request->isFromOplogApplication());
- return _driver.parse(_request->getUpdates(), _arrayFilters, _request->isMulti());
+ _driver.parse(_request->getUpdates(), _arrayFilters, _request->isMulti());
}
Status ParsedUpdate::parseArrayFilters() {
diff --git a/src/mongo/db/ops/parsed_update.h b/src/mongo/db/ops/parsed_update.h
index 8e006f461d1..f6334650244 100644
--- a/src/mongo/db/ops/parsed_update.h
+++ b/src/mongo/db/ops/parsed_update.h
@@ -131,7 +131,7 @@ private:
/**
* Parses the update-descriptor portion of the update request.
*/
- Status parseUpdate();
+ void parseUpdate();
/**
* Parses the array filters portion of the update request.
diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp
index 85664098e4d..4cacd35d047 100644
--- a/src/mongo/db/ops/update.cpp
+++ b/src/mongo/db/ops/update.cpp
@@ -114,19 +114,14 @@ BSONObj applyUpdateOperators(OperationContext* opCtx,
boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
UpdateDriver driver(std::move(expCtx));
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- Status status = driver.parse(operators, arrayFilters);
- if (!status.isOK()) {
- uasserted(16838, status.reason());
- }
+ driver.parse(operators, arrayFilters);
mutablebson::Document doc(from, mutablebson::Document::kInPlaceDisabled);
const bool validateForStorage = false;
const FieldRefSet emptyImmutablePaths;
- status = driver.update(StringData(), &doc, validateForStorage, emptyImmutablePaths);
- if (!status.isOK()) {
- uasserted(16839, status.reason());
- }
+
+ uassertStatusOK(driver.update(StringData(), &doc, validateForStorage, emptyImmutablePaths));
return doc.getObject();
}
diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp
index d8b824316cb..761f914be83 100644
--- a/src/mongo/db/update/update_driver.cpp
+++ b/src/mongo/db/update/update_driver.cpp
@@ -149,7 +149,7 @@ bool parseUpdateExpression(
UpdateDriver::UpdateDriver(const boost::intrusive_ptr<ExpressionContext>& expCtx)
: _expCtx(expCtx) {}
-Status UpdateDriver::parse(
+void UpdateDriver::parse(
const BSONObj& updateExpr,
const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters,
const bool multi) {
@@ -157,16 +157,14 @@ Status UpdateDriver::parse(
// Check if the update expression is a full object replacement.
if (isDocReplacement(updateExpr)) {
- if (multi) {
- return Status(ErrorCodes::FailedToParse, "multi update only works with $ operators");
- }
+ uassert(ErrorCodes::FailedToParse, "multi update only works with $ operators", !multi);
_root = stdx::make_unique<ObjectReplaceNode>(updateExpr);
// Register the fact that this driver will only do full object replacements.
_replacementMode = true;
- return Status::OK();
+ return;
}
// Register the fact that this driver is not doing a full object replacement.
@@ -178,20 +176,16 @@ Status UpdateDriver::parse(
// we parse $v and check its value for compatibility.
BSONElement updateSemanticsElement = updateExpr[LogBuilder::kUpdateSemanticsFieldName];
if (updateSemanticsElement) {
- if (!_fromOplogApplication) {
- return {ErrorCodes::FailedToParse, "The $v update field is only recognized internally"};
- }
- auto statusWithUpdateSemantics = updateSemanticsFromElement(updateSemanticsElement);
- if (!statusWithUpdateSemantics.isOK()) {
- return statusWithUpdateSemantics.getStatus();
- }
+ uassert(ErrorCodes::FailedToParse,
+ "The $v update field is only recognized internally",
+ _fromOplogApplication);
+
+ uassertStatusOK(updateSemanticsFromElement(updateSemanticsElement));
}
auto root = stdx::make_unique<UpdateObjectNode>();
_positional = parseUpdateExpression(updateExpr, root.get(), _expCtx, arrayFilters);
_root = std::move(root);
-
- return Status::OK();
}
Status UpdateDriver::populateDocumentWithQueryFields(OperationContext* opCtx,
diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h
index d754a4f58f4..8345958641b 100644
--- a/src/mongo/db/update/update_driver.h
+++ b/src/mongo/db/update/update_driver.h
@@ -51,13 +51,12 @@ public:
UpdateDriver(const boost::intrusive_ptr<ExpressionContext>& expCtx);
/**
- * Parses the 'updateExpr' update expression into the '_root' member variable. Uasserts or
- * returns a non-ok status if 'updateExpr' fails to parse.
+ * Parses the 'updateExpr' update expression into the '_root' member variable. Uasserts
+ * if 'updateExpr' fails to parse.
*/
- Status parse(
- const BSONObj& updateExpr,
- const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>>& arrayFilters,
- const bool multi = false);
+ void 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 1911c417f0a..10d9c8105bd 100644
--- a/src/mongo/db/update/update_driver_test.cpp
+++ b/src/mongo/db/update/update_driver_test.cpp
@@ -45,6 +45,15 @@
#include "mongo/db/update_index_data.h"
#include "mongo/unittest/unittest.h"
+#define ASSERT_DOES_NOT_THROW(EXPRESSION) \
+ try { \
+ EXPRESSION; \
+ } catch (const AssertionException& e) { \
+ ::mongoutils::str::stream err; \
+ err << "Threw an exception incorrectly: " << e.toString(); \
+ ::mongo::unittest::TestAssertionFailure(__FILE__, __LINE__, err).stream(); \
+ }
+
namespace mongo {
namespace {
@@ -54,7 +63,7 @@ TEST(Parse, Normal) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters));
ASSERT_FALSE(driver.isDocReplacement());
}
@@ -62,7 +71,7 @@ TEST(Parse, MultiMods) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters));
ASSERT_FALSE(driver.isDocReplacement());
}
@@ -70,7 +79,7 @@ TEST(Parse, MixingMods) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters));
ASSERT_FALSE(driver.isDocReplacement());
}
@@ -78,7 +87,7 @@ TEST(Parse, ObjectReplacment) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters));
ASSERT_TRUE(driver.isDocReplacement());
}
@@ -87,7 +96,7 @@ TEST(Parse, EmptyMod) {
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
ASSERT_THROWS_CODE_AND_WHAT(
- driver.parse(fromjson("{$set:{}}"), arrayFilters).transitional_ignore(),
+ driver.parse(fromjson("{$set:{}}"), arrayFilters),
AssertionException,
ErrorCodes::FailedToParse,
"'$set' is empty. You must specify a field like so: {$set: {<field>: ...}}");
@@ -97,23 +106,21 @@ TEST(Parse, WrongMod) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_THROWS_CODE_AND_WHAT(
- driver.parse(fromjson("{$xyz:{a:1}}"), arrayFilters).transitional_ignore(),
- AssertionException,
- ErrorCodes::FailedToParse,
- "Unknown modifier: $xyz");
+ ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$xyz:{a:1}}"), arrayFilters),
+ AssertionException,
+ ErrorCodes::FailedToParse,
+ "Unknown modifier: $xyz");
}
TEST(Parse, WrongType) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_THROWS_CODE_AND_WHAT(
- driver.parse(fromjson("{$set:[{a:1}]}"), arrayFilters).transitional_ignore(),
- AssertionException,
- ErrorCodes::FailedToParse,
- "Modifiers operate on fields but we found type array instead. For "
- "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}");
+ ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$set:[{a:1}]}"), arrayFilters),
+ AssertionException,
+ ErrorCodes::FailedToParse,
+ "Modifiers operate on fields but we found type array instead. For "
+ "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}");
}
TEST(Parse, ModsWithLaterObjReplacement) {
@@ -121,8 +128,7 @@ TEST(Parse, ModsWithLaterObjReplacement) {
UpdateDriver driver(expCtx);
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(),
+ driver.parse(fromjson("{$set:{a:1}, obj: \"obj replacement\"}"), arrayFilters),
AssertionException,
ErrorCodes::FailedToParse,
"Unknown modifier: obj");
@@ -132,7 +138,7 @@ TEST(Parse, SetOnInsert) {
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters));
ASSERT_FALSE(driver.isDocReplacement());
}
@@ -143,7 +149,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) {
UpdateDriver driver(expCtx);
std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters;
- ASSERT_OK(driver.parse(updateDocument, arrayFilters));
+ ASSERT_DOES_NOT_THROW(driver.parse(updateDocument, arrayFilters));
const bool validateForStorage = true;
const FieldRefSet emptyImmutablePaths;
@@ -169,8 +175,8 @@ public:
: _opCtx(_serviceContext.makeOperationContext()),
_driverOps(new UpdateDriver(new ExpressionContext(_opCtx.get(), nullptr))),
_driverRepl(new UpdateDriver(new ExpressionContext(_opCtx.get(), nullptr))) {
- _driverOps->parse(fromjson("{$set:{'_':1}}"), _arrayFilters).transitional_ignore();
- _driverRepl->parse(fromjson("{}"), _arrayFilters).transitional_ignore();
+ _driverOps->parse(fromjson("{$set:{'_':1}}"), _arrayFilters);
+ _driverRepl->parse(fromjson("{}"), _arrayFilters);
}
mutablebson::Document& doc() {