summaryrefslogtreecommitdiff
path: root/src/mongo/client
diff options
context:
space:
mode:
authorDavid Storch <david.storch@mongodb.com>2022-06-10 21:50:45 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-06-10 22:53:08 +0000
commitf6b83615b8a3435193e501424bf4b9b91f9e8a1d (patch)
treec97eb170d89b19b03392e8e5ddd1671982b2fb1a /src/mongo/client
parent8fca1562eae7c9441c664a5868c220b4b2aad050 (diff)
downloadmongo-f6b83615b8a3435193e501424bf4b9b91f9e8a1d.tar.gz
SERVER-65955 Migrate shell exhaust path onto modern internal client API
In doing so, this also fixes the shell's C++ native query path to correctly handle negative limit. The patch also includes additional preparatory work for deleting the query_DEPRECATED() internal client API.
Diffstat (limited to 'src/mongo/client')
-rw-r--r--src/mongo/client/SConscript17
-rw-r--r--src/mongo/client/client_deprecated.cpp284
-rw-r--r--src/mongo/client/client_deprecated.h (renamed from src/mongo/client/query.h)23
-rw-r--r--src/mongo/client/dbclient_base.cpp32
-rw-r--r--src/mongo/client/dbclient_base.h37
-rw-r--r--src/mongo/client/dbclient_connection.cpp2
-rw-r--r--src/mongo/client/dbclient_connection.h5
-rw-r--r--src/mongo/client/dbclient_cursor.cpp242
-rw-r--r--src/mongo/client/dbclient_cursor.h11
-rw-r--r--src/mongo/client/dbclient_cursor_test.cpp132
-rw-r--r--src/mongo/client/dbclient_rs.cpp22
-rw-r--r--src/mongo/client/dbclient_rs.h6
-rw-r--r--src/mongo/client/dbclient_rs_test.cpp4
-rw-r--r--src/mongo/client/query.cpp135
14 files changed, 459 insertions, 493 deletions
diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript
index 1e613f942a0..b04eca892a9 100644
--- a/src/mongo/client/SConscript
+++ b/src/mongo/client/SConscript
@@ -165,29 +165,20 @@ env.Library(
],
)
-env.Library(
- target='client_query',
- source=[
- 'query.cpp',
- ],
- LIBDEPS=[
- '$BUILD_DIR/mongo/base',
- 'read_preference',
- ],
-)
-
clientDriverEnv = env.Clone()
clientDriverEnv.InjectThirdParty('asio')
clientDriverEnv.Library(
target='clientdriver_minimal',
source=[
+ 'client_api_version_parameters.idl',
+ 'client_deprecated.cpp',
'dbclient_base.cpp',
'dbclient_cursor.cpp',
'index_spec.cpp',
- 'client_api_version_parameters.idl',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/dbmessage',
'$BUILD_DIR/mongo/db/pipeline/aggregation_request_helper',
'$BUILD_DIR/mongo/db/query/command_request_response',
@@ -196,8 +187,8 @@ clientDriverEnv.Library(
'$BUILD_DIR/mongo/rpc/command_status',
'$BUILD_DIR/mongo/rpc/rpc',
'authentication',
- 'client_query',
'connection_string',
+ 'read_preference',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/idl/idl_parser',
diff --git a/src/mongo/client/client_deprecated.cpp b/src/mongo/client/client_deprecated.cpp
new file mode 100644
index 00000000000..e8bbf0542f3
--- /dev/null
+++ b/src/mongo/client/client_deprecated.cpp
@@ -0,0 +1,284 @@
+/**
+ * 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
+
+const BSONField<BSONObj> Query::ReadPrefField("$readPreference");
+
+void Query::makeComplex() {
+ if (isComplex())
+ return;
+ BSONObjBuilder b;
+ b.append("query", obj);
+ obj = b.obj();
+}
+
+Query& Query::sort(const BSONObj& s) {
+ appendComplex("orderby", s);
+ return *this;
+}
+
+Query& Query::hint(BSONObj keyPattern) {
+ appendComplex("$hint", keyPattern);
+ return *this;
+}
+
+Query& Query::readPref(ReadPreference pref, const BSONArray& tags) {
+ appendComplex(ReadPrefField.name().c_str(),
+ ReadPreferenceSetting(pref, TagSet(tags)).toInnerBSON());
+ return *this;
+}
+
+bool Query::isComplex(bool* hasDollar) const {
+ return isComplexQueryObj(obj, hasDollar);
+}
+
+Query& Query::appendElements(BSONObj elements) {
+ makeComplex();
+ BSONObjBuilder b(std::move(obj));
+ b.appendElements(elements);
+ obj = b.obj();
+ return *this;
+}
+
+Query& Query::requestResumeToken(bool enable) {
+ appendComplex("$_requestResumeToken", enable);
+ return *this;
+}
+
+Query& Query::resumeAfter(BSONObj point) {
+ appendComplex("$_resumeAfter", point);
+ return *this;
+}
+
+Query& Query::maxTimeMS(long long timeout) {
+ appendComplex("$maxTimeMS", timeout);
+ return *this;
+}
+
+Query& Query::term(long long value) {
+ appendComplex("term", value);
+ return *this;
+}
+
+Query& Query::readConcern(BSONObj rc) {
+ appendComplex("readConcern", rc);
+ return *this;
+}
+
+Query& Query::readOnce(bool enable) {
+ appendComplex("$readOnce", enable);
+ return *this;
+}
+
+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/query.h b/src/mongo/client/client_deprecated.h
index af85022fb07..d8eb80e5afa 100644
--- a/src/mongo/client/query.h
+++ b/src/mongo/client/client_deprecated.h
@@ -31,9 +31,16 @@
#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 {
/**
* Represents a subset of query settings, such as sort, hint, etc. It is only used in the context of
@@ -43,8 +50,6 @@ namespace mongo {
class Query {
public:
static const BSONField<BSONObj> ReadPrefField;
- static const BSONField<std::string> ReadPrefModeField;
- static const BSONField<BSONArray> ReadPrefTagsField;
/**
* Creating a Query object from raw BSON is on its way out. Please don't add new callers under
@@ -84,8 +89,6 @@ public:
*/
Query& readPref(ReadPreference pref, const BSONArray& tags);
- BSONObj getFilter() const;
-
/**
* A temporary accessor that returns a reference to the internal BSON object. No new callers
* should be introduced!
@@ -115,7 +118,6 @@ private:
* @return true if this query has an orderby, hint, or some other field
*/
bool isComplex(bool* hasDollar = nullptr) const;
- static bool isComplex(const BSONObj& obj, bool* hasDollar = nullptr);
void makeComplex();
template <class T>
@@ -131,4 +133,15 @@ inline std::ostream& operator<<(std::ostream& s, const Query& q) {
return s << q.getFullSettingsDeprecated().toString();
}
+/**
+ * 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_base.cpp b/src/mongo/client/dbclient_base.cpp
index e0022ab5d03..cbef18c6867 100644
--- a/src/mongo/client/dbclient_base.cpp
+++ b/src/mongo/client/dbclient_base.cpp
@@ -584,15 +584,16 @@ bool DBClientBase::exists(const string& ns) {
const uint64_t DBClientBase::INVALID_SOCK_CREATION_TIME = std::numeric_limits<uint64_t>::max();
-unique_ptr<DBClientCursor> DBClientBase::query_DEPRECATED(const NamespaceStringOrUUID& nsOrUuid,
- const BSONObj& filter,
- const Query& querySettings,
- int limit,
- int nToSkip,
- const BSONObj* fieldsToReturn,
- int queryOptions,
- int batchSize,
- boost::optional<BSONObj> readConcernObj) {
+unique_ptr<DBClientCursor> DBClientBase::query_DEPRECATED(
+ const NamespaceStringOrUUID& nsOrUuid,
+ const BSONObj& filter,
+ const client_deprecated::Query& querySettings,
+ int limit,
+ int nToSkip,
+ const BSONObj* fieldsToReturn,
+ int queryOptions,
+ int batchSize,
+ boost::optional<BSONObj> readConcernObj) {
unique_ptr<DBClientCursor> c(new DBClientCursor(this,
nsOrUuid,
filter,
@@ -609,8 +610,10 @@ unique_ptr<DBClientCursor> DBClientBase::query_DEPRECATED(const NamespaceStringO
}
std::unique_ptr<DBClientCursor> DBClientBase::find(FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref) {
- auto cursor = std::make_unique<DBClientCursor>(this, std::move(findRequest), readPref);
+ const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode) {
+ auto cursor = std::make_unique<DBClientCursor>(
+ this, std::move(findRequest), readPref, exhaustMode == ExhaustMode::kOn);
if (cursor->init()) {
return cursor;
}
@@ -619,8 +622,9 @@ std::unique_ptr<DBClientCursor> DBClientBase::find(FindCommandRequest findReques
void DBClientBase::find(FindCommandRequest findRequest,
const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode,
std::function<void(const BSONObj&)> callback) {
- auto cursor = this->find(std::move(findRequest), readPref);
+ auto cursor = this->find(std::move(findRequest), readPref, exhaustMode);
while (cursor->more()) {
callback(cursor->nextSafe());
}
@@ -632,7 +636,7 @@ BSONObj DBClientBase::findOne(FindCommandRequest findRequest,
"caller cannot provide a limit when calling DBClientBase::findOne()",
!findRequest.getLimit());
findRequest.setLimit(1);
- auto cursor = this->find(std::move(findRequest), readPref);
+ auto cursor = this->find(std::move(findRequest), readPref, ExhaustMode::kOff);
uassert(5951201, "DBClientBase::findOne() could not produce cursor", cursor);
@@ -657,7 +661,7 @@ unsigned long long DBClientBase::query_DEPRECATED(
std::function<void(DBClientCursorBatchIterator&)> f,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
const BSONObj* fieldsToReturn,
int queryOptions,
int batchSize,
diff --git a/src/mongo/client/dbclient_base.h b/src/mongo/client/dbclient_base.h
index 28dda9ada30..0a1c7bdd77d 100644
--- a/src/mongo/client/dbclient_base.h
+++ b/src/mongo/client/dbclient_base.h
@@ -35,11 +35,11 @@
#include "mongo/base/string_data.h"
#include "mongo/client/authenticate.h"
#include "mongo/client/client_api_version_parameters_gen.h"
+#include "mongo/client/client_deprecated.h"
#include "mongo/client/connection_string.h"
#include "mongo/client/dbclient_cursor.h"
#include "mongo/client/index_spec.h"
#include "mongo/client/mongo_uri.h"
-#include "mongo/client/query.h"
#include "mongo/client/read_preference.h"
#include "mongo/config.h"
#include "mongo/db/dbmessage.h"
@@ -73,6 +73,15 @@ std::string nsGetDB(const std::string& ns);
std::string nsGetCollection(const std::string& ns);
/**
+ * Allows callers of the internal client 'find()' API below to request an exhaust cursor.
+ *
+ * Such cursors use a special OP_MSG facility under the hood. When exhaust is requested, the server
+ * writes the full results of the query into the socket (split into getMore batches), without
+ * waiting for explicit getMore requests from the client.
+ */
+enum class ExhaustMode { kOn, kOff };
+
+/**
* Abstract class that implements the core db operations.
*/
class DBClientBase {
@@ -507,15 +516,21 @@ public:
* Issues a find command described by 'findRequest', and returns the resulting cursor.
*/
virtual std::unique_ptr<DBClientCursor> find(FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref);
+ const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode);
/**
- * Identical to the 'find()' overload above, but uses a default value of "primary" for the read
- * preference.
+ * Convenience overloads. Identical to the 'find()' overload above, but default values of
+ * "primary" read preference and 'ExhaustMode::kOff' are used when not supplied by the caller.
*/
std::unique_ptr<DBClientCursor> find(FindCommandRequest findRequest) {
ReadPreferenceSetting defaultReadPref{};
- return find(std::move(findRequest), defaultReadPref);
+ return find(std::move(findRequest), defaultReadPref, ExhaustMode::kOff);
+ }
+
+ std::unique_ptr<DBClientCursor> find(FindCommandRequest findRequest,
+ const ReadPreferenceSetting& readPref) {
+ return find(std::move(findRequest), readPref, ExhaustMode::kOff);
}
/**
@@ -523,8 +538,16 @@ public:
* returning a cursor to the caller, iterates the cursor under the hood and calls the provided
* 'callback' function against each of the documents produced by the cursor.
*/
+ void find(FindCommandRequest findRequest, std::function<void(const BSONObj&)> callback) {
+ find(std::move(findRequest),
+ ReadPreferenceSetting{},
+ ExhaustMode::kOff,
+ std::move(callback));
+ }
+
void find(FindCommandRequest findRequest,
const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode,
std::function<void(const BSONObj&)> callback);
/**
@@ -560,7 +583,7 @@ public:
virtual std::unique_ptr<DBClientCursor> query_DEPRECATED(
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings = Query(),
+ const client_deprecated::Query& querySettings = client_deprecated::Query(),
int limit = 0,
int nToSkip = 0,
const BSONObj* fieldsToReturn = nullptr,
@@ -571,7 +594,7 @@ public:
std::function<void(DBClientCursorBatchIterator&)> f,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings = Query(),
+ const client_deprecated::Query& querySettings = client_deprecated::Query(),
const BSONObj* fieldsToReturn = nullptr,
int queryOptions = QueryOption_Exhaust,
int batchSize = 0,
diff --git a/src/mongo/client/dbclient_connection.cpp b/src/mongo/client/dbclient_connection.cpp
index 1c84cb370bf..c3651edb01c 100644
--- a/src/mongo/client/dbclient_connection.cpp
+++ b/src/mongo/client/dbclient_connection.cpp
@@ -629,7 +629,7 @@ unsigned long long DBClientConnection::query_DEPRECATED(
std::function<void(DBClientCursorBatchIterator&)> f,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
const BSONObj* fieldsToReturn,
int queryOptions,
int batchSize,
diff --git a/src/mongo/client/dbclient_connection.h b/src/mongo/client/dbclient_connection.h
index 9187852758d..45ffcf97b78 100644
--- a/src/mongo/client/dbclient_connection.h
+++ b/src/mongo/client/dbclient_connection.h
@@ -37,7 +37,6 @@
#include "mongo/client/dbclient_base.h"
#include "mongo/client/index_spec.h"
#include "mongo/client/mongo_uri.h"
-#include "mongo/client/query.h"
#include "mongo/client/read_preference.h"
#include "mongo/config.h"
#include "mongo/db/dbmessage.h"
@@ -146,7 +145,7 @@ public:
std::unique_ptr<DBClientCursor> query_DEPRECATED(
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings = Query(),
+ const client_deprecated::Query& querySettings = client_deprecated::Query(),
int limit = 0,
int nToSkip = 0,
const BSONObj* fieldsToReturn = nullptr,
@@ -169,7 +168,7 @@ public:
std::function<void(DBClientCursorBatchIterator&)>,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
const BSONObj* fieldsToReturn,
int queryOptions,
int batchSize = 0,
diff --git a/src/mongo/client/dbclient_cursor.cpp b/src/mongo/client/dbclient_cursor.cpp
index 735c8a28d00..33fb9e86508 100644
--- a/src/mongo/client/dbclient_cursor.cpp
+++ b/src/mongo/client/dbclient_cursor.cpp
@@ -27,13 +27,6 @@
* it in the license file.
*/
-/**
- * Connect to a Mongo database as a database, from C++.
- */
-
-
-#include "mongo/platform/basic.h"
-
#include "mongo/client/dbclient_cursor.h"
#include <memory>
@@ -106,134 +99,19 @@ Message assembleFromFindCommandRequest(DBClientBase* client,
return opMsgRequest.serialize();
}
-/**
- * Initializes options based on the value of the 'options' bit vector.
- *
- * This contains flags such as tailable, exhaust, and noCursorTimeout.
- */
-void initFromInt(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: ...}
- *
- * Although the OP_QUERY wire protocol message is no longer ever sent over the wire by the internal
- * client, callers of the internal client may still specify the operation they want to perform using
- * an OP_QUERY-inspired format until DBClientCursor's legacy API is removed.
- */
-Status initFullQuery(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.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());
- }
- }
- }
+std::unique_ptr<FindCommandRequest> fromLegacyQuery(NamespaceStringOrUUID nssOrUuid,
+ const BSONObj& filter,
+ const client_deprecated::Query& querySettings,
+ const BSONObj& proj,
+ int ntoskip,
+ int queryOptions) {
+ auto findCommand = std::make_unique<FindCommandRequest>(std::move(nssOrUuid));
- return Status::OK();
-}
+ client_deprecated::initFindFromLegacyOptions(
+ querySettings.getFullSettingsDeprecated(), queryOptions, findCommand.get());
+ findCommand->setFilter(filter.getOwned());
-Status initFindCommandRequest(int ntoskip,
- int queryOptions,
- const BSONObj& filter,
- const Query& querySettings,
- const BSONObj& proj,
- FindCommandRequest* findCommand) {
if (!proj.isEmpty()) {
findCommand->setProjection(proj.getOwned());
}
@@ -241,57 +119,32 @@ Status initFindCommandRequest(int ntoskip,
findCommand->setSkip(ntoskip);
}
- // Initialize flags passed as 'queryOptions' bit vector.
- initFromInt(queryOptions, findCommand);
-
- findCommand->setFilter(filter.getOwned());
- Status status = initFullQuery(querySettings.getFullSettingsDeprecated(), findCommand);
- if (!status.isOK()) {
- return status;
- }
-
- // It's not possible to specify readConcern in a legacy query message, so initialize it to
- // an empty readConcern object, ie. equivalent to `readConcern: {}`. This ensures that
- // mongos passes this empty readConcern to shards.
- findCommand->setReadConcern(BSONObj());
-
- return query_request_helper::validateFindCommandRequest(*findCommand);
-}
-
-StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQuery(NamespaceStringOrUUID nssOrUuid,
- const BSONObj& filter,
- const Query& querySettings,
- const BSONObj& proj,
- int ntoskip,
- int queryOptions) {
- auto findCommand = std::make_unique<FindCommandRequest>(std::move(nssOrUuid));
-
- Status status = initFindCommandRequest(
- ntoskip, queryOptions, filter, querySettings, proj, findCommand.get());
- if (!status.isOK()) {
- return status;
- }
+ uassertStatusOK(query_request_helper::validateFindCommandRequest(*findCommand));
- return std::move(findCommand);
+ return findCommand;
}
int queryOptionsFromFindCommand(const FindCommandRequest& findCmd,
- const ReadPreferenceSetting& readPref) {
+ const ReadPreferenceSetting& readPref,
+ bool isExhaust) {
int queryOptions = 0;
if (readPref.canRunOnSecondary()) {
- queryOptions = queryOptions & QueryOption_SecondaryOk;
+ queryOptions = queryOptions | QueryOption_SecondaryOk;
}
if (findCmd.getTailable()) {
- queryOptions = queryOptions & QueryOption_CursorTailable;
+ queryOptions = queryOptions | QueryOption_CursorTailable;
}
if (findCmd.getNoCursorTimeout()) {
- queryOptions = queryOptions & QueryOption_NoCursorTimeout;
+ queryOptions = queryOptions | QueryOption_NoCursorTimeout;
}
if (findCmd.getAwaitData()) {
- queryOptions = queryOptions & QueryOption_AwaitData;
+ queryOptions = queryOptions | QueryOption_AwaitData;
}
if (findCmd.getAllowPartialResults()) {
- queryOptions = queryOptions & QueryOption_PartialResults;
+ queryOptions = queryOptions | QueryOption_PartialResults;
+ }
+ if (isExhaust) {
+ queryOptions = queryOptions | QueryOption_Exhaust;
}
return queryOptions;
}
@@ -305,42 +158,28 @@ Message DBClientCursor::initFromLegacyRequest() {
_fieldsToReturn ? *_fieldsToReturn : BSONObj(),
_nToSkip,
_opts);
- // If there was a problem building the query request, report that.
- uassertStatusOK(findCommand.getStatus());
if (_limit) {
- findCommand.getValue()->setLimit(_limit);
+ findCommand->setLimit(_limit);
}
if (_batchSize) {
- findCommand.getValue()->setBatchSize(_batchSize);
+ findCommand->setBatchSize(_batchSize);
}
const BSONObj querySettings = _querySettings.getFullSettingsDeprecated();
- if (querySettings.getBoolField("$readOnce")) {
- // Legacy queries don't handle readOnce.
- findCommand.getValue()->setReadOnce(true);
- }
- if (querySettings.getBoolField(FindCommandRequest::kRequestResumeTokenFieldName)) {
- // Legacy queries don't handle requestResumeToken.
- findCommand.getValue()->setRequestResumeToken(true);
- }
- if (querySettings.hasField(FindCommandRequest::kResumeAfterFieldName)) {
- // Legacy queries don't handle resumeAfter.
- findCommand.getValue()->setResumeAfter(
- querySettings.getObjectField(FindCommandRequest::kResumeAfterFieldName));
- }
- if (auto replTerm = querySettings[FindCommandRequest::kTermFieldName]) {
- // Legacy queries don't handle term.
- findCommand.getValue()->setTerm(replTerm.numberLong());
- }
- // Legacy queries don't handle readConcern.
// We prioritize the readConcern parsed from the query object over '_readConcernObj'.
- if (auto readConcern = querySettings[repl::ReadConcernArgs::kReadConcernFieldName]) {
- findCommand.getValue()->setReadConcern(readConcern.Obj());
- } else if (_readConcernObj) {
- findCommand.getValue()->setReadConcern(_readConcernObj);
+ if (!findCommand->getReadConcern()) {
+ if (_readConcernObj) {
+ findCommand->setReadConcern(_readConcernObj);
+ } else {
+ // If no readConcern was specified, initialize it to an empty readConcern object, ie.
+ // equivalent to `readConcern: {}`. This ensures that mongos passes this empty
+ // readConcern to shards.
+ findCommand->setReadConcern(BSONObj());
+ }
}
- BSONObj cmd = findCommand.getValue()->toBSON(BSONObj());
+
+ BSONObj cmd = findCommand->toBSON(BSONObj());
if (auto readPref = querySettings["$readPreference"]) {
// FindCommandRequest doesn't handle $readPreference.
cmd = BSONObjBuilder(std::move(cmd)).append(readPref).obj();
@@ -593,7 +432,7 @@ void DBClientCursor::attach(AScopedConnection* conn) {
DBClientCursor::DBClientCursor(DBClientBase* client,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
int limit,
int nToSkip,
const BSONObj* fieldsToReturn,
@@ -625,7 +464,7 @@ DBClientCursor::DBClientCursor(DBClientBase* client,
: DBClientCursor(client,
nsOrUuid,
BSONObj(), // filter
- Query(), // querySettings
+ client_deprecated::Query(),
cursorId,
limit,
0, // nToSkip
@@ -640,7 +479,7 @@ DBClientCursor::DBClientCursor(DBClientBase* client,
DBClientCursor::DBClientCursor(DBClientBase* client,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
long long cursorId,
int limit,
int nToSkip,
@@ -672,7 +511,8 @@ DBClientCursor::DBClientCursor(DBClientBase* client,
DBClientCursor::DBClientCursor(DBClientBase* client,
FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref)
+ const ReadPreferenceSetting& readPref,
+ bool isExhaust)
: _client(client),
_originalHost(_client->getServerAddress()),
_nsOrUuid(findRequest.getNamespaceOrUUID()),
@@ -681,7 +521,7 @@ DBClientCursor::DBClientCursor(DBClientBase* client,
_limit(findRequest.getLimit().value_or(0)),
_findRequest(std::move(findRequest)),
_readPref(readPref),
- _opts(queryOptionsFromFindCommand(*_findRequest, _readPref)) {
+ _opts(queryOptionsFromFindCommand(*_findRequest, _readPref, isExhaust)) {
// Internal clients should always pass an explicit readConcern. If the caller did not already
// pass a readConcern than we must explicitly initialize an empty readConcern so that it ends up
// in the serialized version of the find command which will be sent across the wire.
diff --git a/src/mongo/client/dbclient_cursor.h b/src/mongo/client/dbclient_cursor.h
index 520b1c1236c..941eda47318 100644
--- a/src/mongo/client/dbclient_cursor.h
+++ b/src/mongo/client/dbclient_cursor.h
@@ -31,7 +31,7 @@
#include <stack>
-#include "mongo/client/query.h"
+#include "mongo/client/client_deprecated.h"
#include "mongo/db/dbmessage.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
@@ -64,7 +64,7 @@ public:
DBClientCursor(DBClientBase* client,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
int limit,
int nToSkip,
const BSONObj* fieldsToReturn,
@@ -83,7 +83,8 @@ public:
DBClientCursor(DBClientBase* client,
FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref);
+ const ReadPreferenceSetting& readPref,
+ bool isExhaust);
virtual ~DBClientCursor();
@@ -279,7 +280,7 @@ private:
DBClientCursor(DBClientBase* client,
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
long long cursorId,
int limit,
int nToSkip,
@@ -349,7 +350,7 @@ private:
// OP_QUERY-inspired API. If the cursor was constructed using the 'FindCommandRequest'-based
// API, these are initialized to their default values but never used.
BSONObj _filter;
- Query _querySettings;
+ client_deprecated::Query _querySettings;
int _nToSkip = 0;
const BSONObj* _fieldsToReturn = nullptr;
boost::optional<BSONObj> _readConcernObj;
diff --git a/src/mongo/client/dbclient_cursor_test.cpp b/src/mongo/client/dbclient_cursor_test.cpp
index 10a23615ab0..21e9cfcf082 100644
--- a/src/mongo/client/dbclient_cursor_test.cpp
+++ b/src/mongo/client/dbclient_cursor_test.cpp
@@ -150,8 +150,8 @@ TEST_F(DBClientCursorTest, DBClientCursorCallsMetaDataReaderOncePerBatch) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(
- &conn, NamespaceStringOrUUID(nss), BSONObj{}, Query(), 0, 0, nullptr, 0, 0);
+ FindCommandRequest findCmd{nss};
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(2);
// Set up mock 'find' response.
@@ -197,15 +197,8 @@ TEST_F(DBClientCursorTest, DBClientCursorHandlesOpMsgExhaustCorrectly) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_Exhaust,
- 0);
+ FindCommandRequest findCmd{nss};
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, true /*isExhaust*/);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -268,15 +261,8 @@ TEST_F(DBClientCursorTest, DBClientCursorResendsGetMoreIfMoreToComeFlagIsOmitted
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_Exhaust,
- 0);
+ FindCommandRequest findCmd{nss};
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, true /*isExhaust*/);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -356,19 +342,11 @@ TEST_F(DBClientCursorTest, DBClientCursorResendsGetMoreIfMoreToComeFlagIsOmitted
}
TEST_F(DBClientCursorTest, DBClientCursorMoreThrowsExceptionOnNonOKResponse) {
-
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_Exhaust,
- 0);
+ FindCommandRequest findCmd{nss};
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, true /*isExhaust*/);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -395,19 +373,11 @@ TEST_F(DBClientCursorTest, DBClientCursorMoreThrowsExceptionOnNonOKResponse) {
}
TEST_F(DBClientCursorTest, DBClientCursorMoreThrowsExceptionWhenMoreToComeFlagSetWithZeroCursorId) {
-
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_Exhaust,
- 0);
+ FindCommandRequest findCmd{nss};
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, true /*isExhaust*/);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -436,19 +406,12 @@ TEST_F(DBClientCursorTest, DBClientCursorMoreThrowsExceptionWhenMoreToComeFlagSe
}
TEST_F(DBClientCursorTest, DBClientCursorPassesReadOnceFlag) {
-
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query().readOnce(true),
- 0,
- 0,
- nullptr,
- /*QueryOption*/ 0,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setReadOnce(true);
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -473,15 +436,10 @@ TEST_F(DBClientCursorTest, DBClientCursorPassesResumeFields) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query().requestResumeToken(true).resumeAfter(BSON("$recordId" << 5LL)),
- 0,
- 0,
- nullptr,
- /*QueryOption*/ 0,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setRequestResumeToken(true);
+ findCmd.setResumeAfter(BSON("$recordId" << 5LL));
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -514,15 +472,9 @@ TEST_F(DBClientCursorTest, DBClientCursorTailable) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_CursorTailable,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setTailable(true);
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -614,15 +566,10 @@ TEST_F(DBClientCursorTest, DBClientCursorTailableAwaitData) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_CursorTailable | QueryOption_AwaitData,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setTailable(true);
+ findCmd.setAwaitData(true);
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -681,15 +628,10 @@ TEST_F(DBClientCursorTest, DBClientCursorTailableAwaitDataExhaust) {
// Set up the DBClientCursor and a mock client connection.
DBClientConnectionForTest conn;
const NamespaceString nss("test", "coll");
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- BSONObj{},
- Query(),
- 0,
- 0,
- nullptr,
- QueryOption_CursorTailable | QueryOption_AwaitData | QueryOption_Exhaust,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setTailable(true);
+ findCmd.setAwaitData(true);
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, true /*isExhaust*/);
cursor.setBatchSize(0);
// Set up mock 'find' response.
@@ -835,15 +777,15 @@ TEST_F(DBClientCursorTest, DBClientCursorOplogQuery) {
const long long maxTimeMS = 5000LL;
const long long term = 5;
- DBClientCursor cursor(&conn,
- NamespaceStringOrUUID(nss),
- filterObj,
- Query().readConcern(readConcernObj).maxTimeMS(maxTimeMS).term(term),
- 0,
- 0,
- nullptr,
- QueryOption_CursorTailable | QueryOption_AwaitData,
- 0);
+ FindCommandRequest findCmd{nss};
+ findCmd.setFilter(filterObj);
+ findCmd.setReadConcern(readConcernObj);
+ findCmd.setMaxTimeMS(maxTimeMS);
+ findCmd.setTerm(term);
+ findCmd.setTailable(true);
+ findCmd.setAwaitData(true);
+
+ DBClientCursor cursor(&conn, findCmd, ReadPreferenceSetting{}, false);
cursor.setBatchSize(0);
// Set up mock 'find' response.
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp
index 4b130c36142..bf4259dd6ed 100644
--- a/src/mongo/client/dbclient_rs.cpp
+++ b/src/mongo/client/dbclient_rs.cpp
@@ -107,8 +107,8 @@ const size_t MAX_RETRY = 3;
*
* @throws AssertionException if the read preference object is malformed
*/
-std::unique_ptr<ReadPreferenceSetting> _extractReadPref(const Query& querySettings,
- int queryOptions) {
+std::unique_ptr<ReadPreferenceSetting> _extractReadPref(
+ const client_deprecated::Query& querySettings, int queryOptions) {
// Default read pref is primary only or secondary preferred with secondaryOK
const auto defaultReadPref = queryOptions & QueryOption_SecondaryOk
? ReadPreference::SecondaryPreferred
@@ -538,7 +538,8 @@ void DBClientReplicaSet::remove(const string& ns,
}
std::unique_ptr<DBClientCursor> DBClientReplicaSet::find(FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref) {
+ const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode) {
invariant(findRequest.getNamespaceOrUUID().nss());
const std::string nss = findRequest.getNamespaceOrUUID().nss()->ns();
if (_isSecondaryQuery(nss, findRequest.toBSON(BSONObj{}), readPref)) {
@@ -562,7 +563,8 @@ std::unique_ptr<DBClientCursor> DBClientReplicaSet::find(FindCommandRequest find
break;
}
- std::unique_ptr<DBClientCursor> cursor = conn->find(findRequest, readPref);
+ std::unique_ptr<DBClientCursor> cursor =
+ conn->find(findRequest, readPref, exhaustMode);
return checkSecondaryQueryResult(std::move(cursor));
} catch (const DBException& ex) {
@@ -587,13 +589,13 @@ std::unique_ptr<DBClientCursor> DBClientReplicaSet::find(FindCommandRequest find
"dbclient_rs query to primary node",
"replicaSet"_attr = _getMonitor()->getName());
- return checkPrimary()->find(std::move(findRequest), readPref);
+ return checkPrimary()->find(std::move(findRequest), readPref, exhaustMode);
}
unique_ptr<DBClientCursor> DBClientReplicaSet::query_DEPRECATED(
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
int limit,
int nToSkip,
const BSONObj* fieldsToReturn,
@@ -824,8 +826,8 @@ void DBClientReplicaSet::say(Message& toSend, bool isRetry, string* actualServer
DbMessage dm(toSend);
QueryMessage qm(dm);
- shared_ptr<ReadPreferenceSetting> readPref(
- _extractReadPref(Query::fromBSONDeprecated(qm.query), qm.queryOptions));
+ shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(
+ client_deprecated::Query::fromBSONDeprecated(qm.query), qm.queryOptions));
if (_isSecondaryQuery(qm.ns, qm.query, *readPref)) {
LOGV2_DEBUG(20141,
3,
@@ -990,8 +992,8 @@ bool DBClientReplicaSet::call(Message& toSend,
QueryMessage qm(dm);
ns = qm.ns;
- shared_ptr<ReadPreferenceSetting> readPref(
- _extractReadPref(Query::fromBSONDeprecated(qm.query), qm.queryOptions));
+ shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(
+ client_deprecated::Query::fromBSONDeprecated(qm.query), qm.queryOptions));
if (_isSecondaryQuery(ns, qm.query, *readPref)) {
LOGV2_DEBUG(
20145,
diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h
index d31ff67f5b6..ebab6854ffc 100644
--- a/src/mongo/client/dbclient_rs.h
+++ b/src/mongo/client/dbclient_rs.h
@@ -57,6 +57,7 @@ typedef std::shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr;
*/
class DBClientReplicaSet : public DBClientBase {
public:
+ using DBClientBase::find;
using DBClientBase::query_DEPRECATED;
/** Call connect() after constructing. autoReconnect is always on for DBClientReplicaSet
@@ -89,13 +90,14 @@ public:
// ----------- simple functions --------------
std::unique_ptr<DBClientCursor> find(FindCommandRequest findRequest,
- const ReadPreferenceSetting& readPref) override;
+ const ReadPreferenceSetting& readPref,
+ ExhaustMode exhaustMode) override;
/** throws userassertion "no primary found" */
std::unique_ptr<DBClientCursor> query_DEPRECATED(
const NamespaceStringOrUUID& nsOrUuid,
const BSONObj& filter,
- const Query& querySettings,
+ const client_deprecated::Query& querySettings,
int limit = 0,
int nToSkip = 0,
const BSONObj* fieldsToReturn = nullptr,
diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp
index c04a2ddd7aa..2bbbc78858a 100644
--- a/src/mongo/client/dbclient_rs_test.cpp
+++ b/src/mongo/client/dbclient_rs_test.cpp
@@ -167,7 +167,7 @@ void assertWithBothQueryApis(DBClientReplicaSet& replConn,
replConn.find(FindCommandRequest{nss}, ReadPreferenceSetting{readPref});
assertionFunc(std::move(cursor));
- Query readPrefHolder;
+ client_deprecated::Query readPrefHolder;
readPrefHolder.readPref(readPref, BSONArray{});
cursor = replConn.query_DEPRECATED(nss, BSONObj{}, readPrefHolder);
assertionFunc(std::move(cursor));
@@ -186,7 +186,7 @@ void assertBothQueryApisThrow(DBClientReplicaSet& replConn,
ASSERT_THROWS(replConn.find(FindCommandRequest{nss}, ReadPreferenceSetting{readPref}),
AssertionException);
- Query readPrefHolder;
+ client_deprecated::Query readPrefHolder;
readPrefHolder.readPref(readPref, BSONArray{});
ASSERT_THROWS(replConn.query_DEPRECATED(nss, BSONObj{}, readPrefHolder), AssertionException);
}
diff --git a/src/mongo/client/query.cpp b/src/mongo/client/query.cpp
deleted file mode 100644
index 39d7e1316e2..00000000000
--- a/src/mongo/client/query.cpp
+++ /dev/null
@@ -1,135 +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/platform/basic.h"
-
-#include "mongo/client/query.h"
-
-#include "mongo/base/status.h"
-#include "mongo/base/status_with.h"
-#include "mongo/bson/util/builder.h"
-
-namespace mongo {
-
-using std::string;
-
-const BSONField<BSONObj> Query::ReadPrefField("$readPreference");
-const BSONField<string> Query::ReadPrefModeField("mode");
-const BSONField<BSONArray> Query::ReadPrefTagsField("tags");
-
-void Query::makeComplex() {
- if (isComplex())
- return;
- BSONObjBuilder b;
- b.append("query", obj);
- obj = b.obj();
-}
-
-Query& Query::sort(const BSONObj& s) {
- appendComplex("orderby", s);
- return *this;
-}
-
-Query& Query::hint(BSONObj keyPattern) {
- appendComplex("$hint", keyPattern);
- return *this;
-}
-
-bool Query::isComplex(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 Query::getFilter() const {
- bool hasDollar;
- if (!isComplex(&hasDollar))
- return obj;
-
- return obj.getObjectField(hasDollar ? "$query" : "query");
-}
-
-Query& Query::readPref(ReadPreference pref, const BSONArray& tags) {
- appendComplex(ReadPrefField.name().c_str(),
- ReadPreferenceSetting(pref, TagSet(tags)).toInnerBSON());
- return *this;
-}
-
-bool Query::isComplex(bool* hasDollar) const {
- return isComplex(obj, hasDollar);
-}
-
-Query& Query::appendElements(BSONObj elements) {
- makeComplex();
- BSONObjBuilder b(std::move(obj));
- b.appendElements(elements);
- obj = b.obj();
- return *this;
-}
-
-Query& Query::requestResumeToken(bool enable) {
- appendComplex("$_requestResumeToken", enable);
- return *this;
-}
-
-Query& Query::resumeAfter(BSONObj point) {
- appendComplex("$_resumeAfter", point);
- return *this;
-}
-
-Query& Query::maxTimeMS(long long timeout) {
- appendComplex("$maxTimeMS", timeout);
- return *this;
-}
-
-Query& Query::term(long long value) {
- appendComplex("term", value);
- return *this;
-}
-
-Query& Query::readConcern(BSONObj rc) {
- appendComplex("readConcern", rc);
- return *this;
-}
-
-Query& Query::readOnce(bool enable) {
- appendComplex("$readOnce", enable);
- return *this;
-}
-} // namespace mongo