summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Storch <david.storch@mongodb.com>2022-09-14 17:17:39 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-14 18:45:53 +0000
commitf599ca57cd8476c88428a53b2d844fde0afbce5e (patch)
treed94de247a301928f96e3ee6f64eb3939a20fbf66 /src
parentcf379f81849b3f8f3d21f661b1eee25379c9a06a (diff)
downloadmongo-f599ca57cd8476c88428a53b2d844fde0afbce5e.tar.gz
SERVER-67116 Remove support for 'preCondition' from applyOps command
Diffstat (limited to 'src')
-rw-r--r--src/mongo/client/SConscript1
-rw-r--r--src/mongo/client/client_deprecated.cpp216
-rw-r--r--src/mongo/client/client_deprecated.h55
-rw-r--r--src/mongo/client/dbclient_rs.cpp1
-rw-r--r--src/mongo/db/commands/apply_ops_cmd.cpp3
-rw-r--r--src/mongo/db/commands/oplog_application_checks.cpp15
-rw-r--r--src/mongo/db/repl/apply_ops.cpp70
-rw-r--r--src/mongo/db/repl/apply_ops.idl7
-rw-r--r--src/mongo/db/repl/apply_ops_command_info.cpp11
-rw-r--r--src/mongo/db/repl/apply_ops_command_info.h1
10 files changed, 11 insertions, 369 deletions
diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript
index 619594b97e5..296e0ec8b8f 100644
--- a/src/mongo/client/SConscript
+++ b/src/mongo/client/SConscript
@@ -172,7 +172,6 @@ clientDriverEnv.Library(
target='clientdriver_minimal',
source=[
'client_api_version_parameters.idl',
- 'client_deprecated.cpp',
'dbclient_base.cpp',
'dbclient_cursor.cpp',
'index_spec.cpp',
diff --git a/src/mongo/client/client_deprecated.cpp b/src/mongo/client/client_deprecated.cpp
deleted file mode 100644
index 2df1d1be3ac..00000000000
--- a/src/mongo/client/client_deprecated.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * 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
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * 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 Server Side 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/client/client_deprecated.h"
-
-#include "mongo/base/status.h"
-#include "mongo/base/status_with.h"
-#include "mongo/bson/util/builder.h"
-#include "mongo/db/query/query_request_helper.h"
-
-namespace mongo {
-namespace client_deprecated {
-
-namespace {
-bool isComplexQueryObj(const BSONObj& obj, bool* hasDollar) {
- if (obj.hasElement("query")) {
- if (hasDollar)
- *hasDollar = false;
- return true;
- }
-
- if (obj.hasElement("$query")) {
- if (hasDollar)
- *hasDollar = true;
- return true;
- }
-
- return false;
-}
-
-BSONObj filterFromOpQueryObj(const BSONObj& obj) {
- bool hasDollar;
- if (!isComplexQueryObj(obj, &hasDollar)) {
- return obj;
- }
-
- return obj.getObjectField(hasDollar ? "$query" : "query");
-}
-
-void initFindFromOptions(int options, FindCommandRequest* findCommand) {
- bool tailable = (options & QueryOption_CursorTailable) != 0;
- bool awaitData = (options & QueryOption_AwaitData) != 0;
- if (awaitData) {
- findCommand->setAwaitData(true);
- }
- if (tailable) {
- findCommand->setTailable(true);
- }
-
- if ((options & QueryOption_NoCursorTimeout) != 0) {
- findCommand->setNoCursorTimeout(true);
- }
- if ((options & QueryOption_PartialResults) != 0) {
- findCommand->setAllowPartialResults(true);
- }
-}
-
-/**
- * Fills out the 'findCommand' output parameter based on the contents of 'querySettings'. Here,
- * 'querySettings' has the same format as the "query" field of the no-longer-supported OP_QUERY wire
- * protocol message. It can look something like this for example:
- *
- * {$query: ..., $hint: ..., $min: ..., $max: ...}
- *
- * Note that this does not set the filter itself on the 'FindCommandRequest' -- this function only
- * deals with options that can be packed into the filter object.
- *
- * Although the OP_QUERY wire protocol message is no longer ever sent over the wire by the internal
- * client, this supports old callers of that still specify the operation they want to perform using
- * an OP_QUERY-inspired format.
- */
-Status initFindFromOpQueryObj(const BSONObj& querySettings, FindCommandRequest* findCommand) {
- for (auto&& e : querySettings) {
- StringData name = e.fieldNameStringData();
-
- if (name == "$orderby" || name == "orderby") {
- if (Object == e.type()) {
- findCommand->setSort(e.embeddedObject().getOwned());
- } else if (Array == e.type()) {
- findCommand->setSort(e.embeddedObject());
-
- // TODO: Is this ever used? I don't think so.
- // Quote:
- // This is for languages whose "objects" are not well ordered (JSON is well
- // ordered).
- // [ { a : ... } , { b : ... } ] -> { a : ..., b : ... }
- // note: this is slow, but that is ok as order will have very few pieces
- BSONObjBuilder b;
- char p[2] = "0";
-
- while (1) {
- BSONObj j = findCommand->getSort().getObjectField(p);
- if (j.isEmpty()) {
- break;
- }
- BSONElement e = j.firstElement();
- if (e.eoo()) {
- return Status(ErrorCodes::BadValue, "bad order array");
- }
- if (!e.isNumber()) {
- return Status(ErrorCodes::BadValue, "bad order array [2]");
- }
- b.append(e);
- (*p)++;
- if (!(*p <= '9')) {
- return Status(ErrorCodes::BadValue, "too many ordering elements");
- }
- }
-
- findCommand->setSort(b.obj());
- } else {
- return Status(ErrorCodes::BadValue, "sort must be object or array");
- }
- } else if (name == "term") {
- findCommand->setTerm(e.safeNumberLong());
- } else if (name == "readConcern") {
- if (e.type() != BSONType::Object) {
- return Status(ErrorCodes::BadValue, "readConcern must be an object");
- }
- findCommand->setReadConcern(e.embeddedObject().getOwned());
- } else if (name.startsWith("$")) {
- name = name.substr(1); // chop first char
- if (name == "min") {
- if (!e.isABSONObj()) {
- return Status(ErrorCodes::BadValue, "$min must be a BSONObj");
- }
- findCommand->setMin(e.embeddedObject().getOwned());
- } else if (name == "max") {
- if (!e.isABSONObj()) {
- return Status(ErrorCodes::BadValue, "$max must be a BSONObj");
- }
- findCommand->setMax(e.embeddedObject().getOwned());
- } else if (name == "hint") {
- if (e.isABSONObj()) {
- findCommand->setHint(e.embeddedObject().getOwned());
- } else if (String == e.type()) {
- findCommand->setHint(e.wrap());
- } else {
- return Status(ErrorCodes::BadValue,
- "$hint must be either a string or nested object");
- }
- } else if (name == "returnKey") {
- // Won't throw.
- if (e.trueValue()) {
- findCommand->setReturnKey(true);
- }
- } else if (name == "showDiskLoc") {
- // Won't throw.
- if (e.trueValue()) {
- findCommand->setShowRecordId(true);
- query_request_helper::addShowRecordIdMetaProj(findCommand);
- }
- } else if (name == "maxTimeMS") {
- StatusWith<int> maxTimeMS = parseMaxTimeMS(e);
- if (!maxTimeMS.isOK()) {
- return maxTimeMS.getStatus();
- }
- findCommand->setMaxTimeMS(maxTimeMS.getValue());
- } else if (name == "readOnce") {
- if (e.booleanSafe()) {
- findCommand->setReadOnce(true);
- }
- } else if (name == "_requestResumeToken") {
- if (e.booleanSafe()) {
- findCommand->setRequestResumeToken(true);
- }
- } else if (name == "_resumeAfter") {
- findCommand->setResumeAfter(e.embeddedObjectUserCheck().getOwned());
- }
- }
- }
-
- return Status::OK();
-}
-
-} // namespace
-
-void initFindFromLegacyOptions(BSONObj bsonOptions, int options, FindCommandRequest* findCommand) {
- invariant(findCommand);
- BSONObj filter = filterFromOpQueryObj(bsonOptions);
- if (!filter.isEmpty()) {
- findCommand->setFilter(filter.getOwned());
- }
-
- uassertStatusOK(initFindFromOpQueryObj(bsonOptions, findCommand));
- initFindFromOptions(options, findCommand);
-}
-
-} // namespace client_deprecated
-} // namespace mongo
diff --git a/src/mongo/client/client_deprecated.h b/src/mongo/client/client_deprecated.h
deleted file mode 100644
index fa4509c62f8..00000000000
--- a/src/mongo/client/client_deprecated.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * 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
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * 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 Server Side 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/bson/json.h"
-#include "mongo/client/read_preference.h"
-#include "mongo/db/query/find_command_gen.h"
-#include "mongo/rpc/message.h"
-
-namespace mongo {
-/**
- * WARNING: Do not add new uses of anything in this namespace! This exists only to support code
- * paths that still use an OP_QUERY-derived query representation. Additional callers should not be
- * added because OP_QUERY is no longer supported by the shell or server.
- */
-namespace client_deprecated {
-/**
- * WARNING: This function exists only to support special code paths that use an OP_QUERY-style query
- * representation (even though the OP_QUERY wire protocol message itself is no longer supported). Do
- * not add new callers.
- *
- * Sets the relevant fields in 'findCommand' based on the 'bsonOptions' object and the 'options' bit
- * vector. 'bsonOptions' is formatted like the query object of an OP_QUERY wire protocol message.
- * Similarly, 'options' is a bit vector which is interpreted like the OP_QUERY flags field.
- */
-void initFindFromLegacyOptions(BSONObj bsonOptions, int options, FindCommandRequest* findCommand);
-} // namespace client_deprecated
-} // namespace mongo
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp
index 6d86e41a936..82aa7cb43a1 100644
--- a/src/mongo/client/dbclient_rs.cpp
+++ b/src/mongo/client/dbclient_rs.cpp
@@ -33,7 +33,6 @@
#include <utility>
#include "mongo/bson/util/builder.h"
-#include "mongo/client/client_deprecated.h"
#include "mongo/client/connpool.h"
#include "mongo/client/dbclient_cursor.h"
#include "mongo/client/global_conn_pool.h"
diff --git a/src/mongo/db/commands/apply_ops_cmd.cpp b/src/mongo/db/commands/apply_ops_cmd.cpp
index 56adcab2cb6..d074ecc3edb 100644
--- a/src/mongo/db/commands/apply_ops_cmd.cpp
+++ b/src/mongo/db/commands/apply_ops_cmd.cpp
@@ -199,8 +199,7 @@ public:
}
std::string help() const override {
- return "internal (sharding)\n{ applyOps : [ ] , preCondition : [ { ns : ... , q : ... , "
- "res : ... } ] }";
+ return "internal command to apply oplog entries\n{ applyOps : [ ] }";
}
Status checkAuthForOperation(OperationContext* opCtx,
diff --git a/src/mongo/db/commands/oplog_application_checks.cpp b/src/mongo/db/commands/oplog_application_checks.cpp
index 80e0e8720e3..02cc6e51366 100644
--- a/src/mongo/db/commands/oplog_application_checks.cpp
+++ b/src/mongo/db/commands/oplog_application_checks.cpp
@@ -258,21 +258,6 @@ Status OplogApplicationChecks::checkAuthForCommand(OperationContext* opCtx,
}
}
- BSONElement preconditions = cmdObj["preCondition"];
- if (!preconditions.eoo()) {
- for (const BSONElement& precondition : preconditions.Array()) {
- checkBSONType(BSONType::Object, precondition);
- BSONElement nsElem = precondition.Obj()["ns"];
- checkBSONType(BSONType::String, nsElem);
- NamespaceString nss(nsElem.checkAndGetStringData());
-
- if (!authSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(nss), ActionType::find)) {
- return Status(ErrorCodes::Unauthorized, "Unauthorized to check precondition");
- }
- }
- }
-
return Status::OK();
}
diff --git a/src/mongo/db/repl/apply_ops.cpp b/src/mongo/db/repl/apply_ops.cpp
index c89a830b459..59512366b11 100644
--- a/src/mongo/db/repl/apply_ops.cpp
+++ b/src/mongo/db/repl/apply_ops.cpp
@@ -30,10 +30,8 @@
#include "mongo/db/repl/apply_ops.h"
#include "mongo/bson/util/bson_extract.h"
-#include "mongo/client/client_deprecated.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
-#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/client.h"
#include "mongo/db/concurrency/exception_util.h"
@@ -44,7 +42,6 @@
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index_builds_coordinator.h"
-#include "mongo/db/matcher/matcher.h"
#include "mongo/db/op_observer/op_observer.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/repl/replication_coordinator.h"
@@ -60,7 +57,6 @@
namespace mongo {
namespace repl {
-constexpr StringData ApplyOps::kPreconditionFieldName;
constexpr StringData ApplyOps::kOplogApplicationModeFieldName;
namespace {
@@ -276,58 +272,6 @@ Status _applyOps(OperationContext* opCtx,
return Status::OK();
}
-Status _checkPrecondition(OperationContext* opCtx,
- const std::vector<BSONObj>& preConditions,
- BSONObjBuilder* result) {
- invariant(opCtx->lockState()->isW());
-
- for (const auto& preCondition : preConditions) {
- if (preCondition["ns"].type() != BSONType::String) {
- return {ErrorCodes::InvalidNamespace,
- str::stream() << "ns in preCondition must be a string, but found type: "
- << typeName(preCondition["ns"].type())};
- }
- const NamespaceString nss(preCondition["ns"].valueStringData());
- if (!nss.isValid()) {
- return {ErrorCodes::InvalidNamespace, "invalid ns: " + nss.ns()};
- }
-
- DBDirectClient db(opCtx);
- // The preconditions come in "q: {{query: {...}, orderby: ..., etc.}}" format. This format
- // is no longer used either internally or over the wire in other contexts. We are using a
- // legacy API from 'client_deprecated' in order to parse this format and convert it into the
- // corresponding find command.
- FindCommandRequest findCmd{nss};
- client_deprecated::initFindFromLegacyOptions(preCondition["q"].Obj(), 0, &findCmd);
- BSONObj realres = db.findOne(std::move(findCmd));
-
- // Get collection default collation.
- auto databaseHolder = DatabaseHolder::get(opCtx);
- auto database = databaseHolder->getDb(opCtx, nss.dbName());
- if (!database) {
- return {ErrorCodes::NamespaceNotFound, "database in ns does not exist: " + nss.ns()};
- }
- CollectionPtr collection =
- CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, nss);
- if (!collection) {
- return {ErrorCodes::NamespaceNotFound, "collection in ns does not exist: " + nss.ns()};
- }
- const CollatorInterface* collator = collection->getDefaultCollator();
-
- // applyOps does not allow any extensions, such as $text, $where, $geoNear, $near,
- // $nearSphere, or $expr.
- boost::intrusive_ptr<ExpressionContext> expCtx(
- new ExpressionContext(opCtx, CollatorInterface::cloneCollator(collator), nss));
- Matcher matcher(preCondition["res"].Obj(), std::move(expCtx));
- if (!matcher.matches(realres)) {
- result->append("got", realres);
- result->append("whatFailed", preCondition);
- return {ErrorCodes::BadValue, "preCondition failed"};
- }
- }
-
- return Status::OK();
-}
} // namespace
Status applyApplyOpsOplogEntry(OperationContext* opCtx,
@@ -359,9 +303,9 @@ Status applyOps(OperationContext* opCtx,
uassert(31056, "applyOps command can't have 'partialTxn' field.", !info.getPartialTxn());
uassert(31240, "applyOps command can't have 'count' field.", !info.getCount());
- // There's one case where we are allowed to take the database lock instead of the global
- // lock - no preconditions; only CRUD ops; and non-atomic mode.
- if (!info.getPreCondition() && info.areOpsCrudOnly() && !info.getAllowAtomic()) {
+ // There's one case where we are allowed to take the database lock instead of the global lock --
+ // only CRUD ops and non-atomic mode.
+ if (info.areOpsCrudOnly() && !info.getAllowAtomic()) {
// TODO SERVER-62880 Once the dbName is of type DatabaseName, pass it directly to the DBlock
DatabaseName databaseName(boost::none, dbName);
dbWriteLock.emplace(opCtx, databaseName, MODE_IX);
@@ -377,14 +321,6 @@ Status applyOps(OperationContext* opCtx,
return Status(ErrorCodes::NotWritablePrimary,
str::stream() << "Not primary while applying ops to database " << dbName);
- if (auto preCondition = info.getPreCondition()) {
- invariant(info.isAtomic());
- auto status = _checkPrecondition(opCtx, *preCondition, result);
- if (!status.isOK()) {
- return status;
- }
- }
-
LOGV2_DEBUG(5854600,
2,
"applyOps command",
diff --git a/src/mongo/db/repl/apply_ops.idl b/src/mongo/db/repl/apply_ops.idl
index 792f6a63d1e..d9a1e17fb1f 100644
--- a/src/mongo/db/repl/apply_ops.idl
+++ b/src/mongo/db/repl/apply_ops.idl
@@ -64,9 +64,10 @@ structs:
cpp_name: preCondition
type: array<object>
optional: true
- description: "applyOps supports checking the documents of existing collections
- before proceeding to execute the given operations. This flag is set to
- true if the 'preCondition' option is provided."
+ description: "No longer supported, but kept here to improve the error message
+ returned to the client. In older versions, applyOps used to support
+ checking the documents of existing collections before proceeding to
+ execute the given operations."
prepare:
type: bool
diff --git a/src/mongo/db/repl/apply_ops_command_info.cpp b/src/mongo/db/repl/apply_ops_command_info.cpp
index 614d0e7c3c0..f8a78e9a555 100644
--- a/src/mongo/db/repl/apply_ops_command_info.cpp
+++ b/src/mongo/db/repl/apply_ops_command_info.cpp
@@ -96,14 +96,9 @@ ApplyOpsCommandInfo::ApplyOpsCommandInfo(const BSONObj& applyOpCmd)
: _areOpsCrudOnly(_parseAreOpsCrudOnly(applyOpCmd)) {
parseProtected(IDLParserContext("applyOps"), applyOpCmd);
- if (getPreCondition()) {
- uassert(ErrorCodes::InvalidOptions,
- "Cannot use preCondition with {allowAtomic: false}",
- getAllowAtomic());
- uassert(ErrorCodes::InvalidOptions,
- "Cannot use preCondition when operations include commands.",
- areOpsCrudOnly());
- }
+ uassert(6711600,
+ "applyOps command no longer supports the 'preCondition' option",
+ !getPreCondition());
}
// static
diff --git a/src/mongo/db/repl/apply_ops_command_info.h b/src/mongo/db/repl/apply_ops_command_info.h
index 0773a25231a..d1c2a7648ac 100644
--- a/src/mongo/db/repl/apply_ops_command_info.h
+++ b/src/mongo/db/repl/apply_ops_command_info.h
@@ -43,7 +43,6 @@ class OperationContext;
namespace repl {
class ApplyOps {
public:
- static constexpr StringData kPreconditionFieldName = "preCondition"_sd;
static constexpr StringData kOplogApplicationModeFieldName = "oplogApplicationMode"_sd;
/**