summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2020-12-15 13:41:29 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-12-15 20:17:40 +0000
commit0c132588e9907c7b123f986a61c3a43cd087381f (patch)
treea83d514dff0689f97e7d9db7b503912767ec9cc9 /src
parentc425bdcf1862d642460211fcf450664233a9e6d0 (diff)
downloadmongo-0c132588e9907c7b123f986a61c3a43cd087381f.tar.gz
SERVER-52545 Define listIndexes with IDL
Diffstat (limited to 'src')
-rw-r--r--src/mongo/bson/bsonelement.h13
-rw-r--r--src/mongo/db/SConscript14
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp20
-rw-r--r--src/mongo/db/commands/list_indexes.cpp54
-rw-r--r--src/mongo/db/create_indexes.idl55
-rw-r--r--src/mongo/db/list_indexes.idl167
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp5
-rw-r--r--src/mongo/db/timeseries/timeseries.idl2
-rw-r--r--src/mongo/idl/basic_types.idl10
-rw-r--r--src/mongo/s/commands/cluster_list_indexes_cmd.cpp6
-rw-r--r--src/mongo/scripting/mozjs/bson.cpp29
-rw-r--r--src/mongo/scripting/mozjs/bson.h3
12 files changed, 330 insertions, 48 deletions
diff --git a/src/mongo/bson/bsonelement.h b/src/mongo/bson/bsonelement.h
index 7c6b86071c7..b3a39c04ce3 100644
--- a/src/mongo/bson/bsonelement.h
+++ b/src/mongo/bson/bsonelement.h
@@ -29,6 +29,7 @@
#pragma once
+#include <algorithm>
#include <cmath>
#include <cstdint>
#include <fmt/format.h>
@@ -377,6 +378,13 @@ public:
*/
int numberInt() const;
+ /** Like numberInt() but with well-defined behavior for doubles that
+ * are NaNs, or too large/small to be represented as int.
+ * NaNs -> 0
+ * very large doubles -> INT_MAX
+ * very small doubles -> INT_MIN */
+ int safeNumberInt() const;
+
/**
* Retrieves the value of this element as a 64 bit integer. If the BSON type is non-numeric,
* returns zero. If the element holds a double, truncates the fractional part.
@@ -950,6 +958,11 @@ inline int BSONElement::numberInt() const {
}
}
+inline int BSONElement::safeNumberInt() const {
+ return static_cast<int>(std::clamp<long long>(
+ safeNumberLong(), std::numeric_limits<int>::min(), std::numeric_limits<int>::max()));
+}
+
inline long long BSONElement::numberLong() const {
switch (type()) {
case NumberDouble:
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 09e32294938..af1e5d8a47c 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -575,10 +575,12 @@ env.Library(
'drop.idl',
'drop_database.idl',
'list_collections.idl',
+ 'list_indexes.idl',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'api_parameters',
+ 'create_indexes_idl',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/bson/mutable/mutable_bson',
@@ -1371,15 +1373,25 @@ env.Library(
)
env.Library(
+ target='create_indexes_idl',
+ source=[
+ 'create_indexes.idl',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/idl/idl_parser',
+ ],
+)
+
+env.Library(
target='sessions_collection',
source=[
'sessions_collection.cpp',
- 'create_indexes.idl',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/client/clientdriver_minimal',
'$BUILD_DIR/mongo/s/write_ops/batch_write_types',
+ 'create_indexes_idl',
'logical_session_id',
],
)
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp
index 0019f1b18ad..8ee6c5c9ca6 100644
--- a/src/mongo/db/catalog/rename_collection.cpp
+++ b/src/mongo/db/catalog/rename_collection.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/catalog/rename_collection.h"
+#include "mongo/bson/unordered_fields_bsonobj_comparator.h"
#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/catalog/document_validation.h"
@@ -750,14 +751,17 @@ void doLocalRenameIfOptionsAndIndexesHaveNotChanged(OperationContext* opCtx,
auto currentIndexes =
listIndexesEmptyListIfMissing(opCtx, targetNs, false /* includeBuildUUIDs */);
- uassert(ErrorCodes::CommandFailed,
- str::stream() << "indexes of target collection " << targetNs.ns()
- << " changed during processing.",
- originalIndexes.size() == currentIndexes.size() &&
- std::equal(originalIndexes.begin(),
- originalIndexes.end(),
- currentIndexes.begin(),
- SimpleBSONObjComparator::kInstance.makeEqualTo()));
+
+ UnorderedFieldsBSONObjComparator comparator;
+ uassert(
+ ErrorCodes::CommandFailed,
+ str::stream() << "indexes of target collection " << targetNs.ns()
+ << " changed during processing.",
+ originalIndexes.size() == currentIndexes.size() &&
+ std::equal(originalIndexes.begin(),
+ originalIndexes.end(),
+ currentIndexes.begin(),
+ [&](auto& lhs, auto& rhs) { return comparator.compare(lhs, rhs) == 0; }));
validateAndRunRenameCollection(opCtx, sourceNs, targetNs, options);
}
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index 1573dfccd36..f366615b0e6 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -27,6 +27,8 @@
* it in the license file.
*/
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
+
#include "mongo/platform/basic.h"
#include <memory>
@@ -44,6 +46,7 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/exec/working_set.h"
#include "mongo/db/index/index_descriptor.h"
+#include "mongo/db/list_indexes_gen.h"
#include "mongo/db/query/cursor_request.h"
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/find_common.h"
@@ -51,6 +54,7 @@
#include "mongo/db/service_context.h"
#include "mongo/db/storage/durable_catalog.h"
#include "mongo/db/storage/storage_engine.h"
+#include "mongo/logv2/log.h"
#include "mongo/util/uuid.h"
namespace mongo {
@@ -62,6 +66,15 @@ using std::vector;
namespace {
+void appendListIndexesCursorReply(CursorId cursorId,
+ const NamespaceString& cursorNss,
+ std::vector<mongo::ListIndexesReplyItem>&& firstBatch,
+ BSONObjBuilder& result) {
+ auto reply =
+ ListIndexesReply(ListIndexesReplyCursor(cursorId, cursorNss, std::move(firstBatch)));
+ reply.serialize(&result);
+}
+
/**
* Lists the indexes for a given collection.
* If 'includeBuildUUIDs' is true, then the index build uuid is also returned alongside the index
@@ -146,19 +159,17 @@ public:
const BSONObj& cmdObj,
BSONObjBuilder& result) {
CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
- const long long defaultBatchSize = std::numeric_limits<long long>::max();
- long long batchSize;
- uassertStatusOK(
- CursorRequest::parseCommandCursorOptions(cmdObj, defaultBatchSize, &batchSize));
-
- auto includeBuildUUIDs = cmdObj["includeBuildUUIDs"].trueValue();
+ const auto parsed = ListIndexes::parse({"listIndexes"}, cmdObj);
+ long long batchSize = std::numeric_limits<long long>::max();
+ if (parsed.getCursor() && parsed.getCursor()->getBatchSize()) {
+ batchSize = *parsed.getCursor()->getBatchSize();
+ }
NamespaceString nss;
std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> exec;
- BSONArrayBuilder firstBatch;
+ std::vector<mongo::ListIndexesReplyItem> firstBatch;
{
- AutoGetCollectionForReadCommand collection(
- opCtx, CommandHelpers::parseNsOrUUID(dbname, cmdObj));
+ AutoGetCollectionForReadCommand collection(opCtx, parsed.getNamespaceOrUUID());
uassert(ErrorCodes::NamespaceNotFound,
str::stream() << "ns does not exist: " << collection.getNss().ns(),
collection);
@@ -167,8 +178,8 @@ public:
auto expCtx = make_intrusive<ExpressionContext>(
opCtx, std::unique_ptr<CollatorInterface>(nullptr), nss);
- auto indexList =
- listIndexesInLock(opCtx, collection.getCollection(), nss, includeBuildUUIDs);
+ auto indexList = listIndexesInLock(
+ opCtx, collection.getCollection(), nss, parsed.getIncludeBuildUUIDs());
auto ws = std::make_unique<WorkingSet>();
auto root = std::make_unique<QueuedDataStage>(expCtx.get(), ws.get());
@@ -190,6 +201,7 @@ public:
PlanYieldPolicy::YieldPolicy::NO_YIELD,
nss));
+ int bytesBuffered = 0;
for (long long objCount = 0; objCount < batchSize; objCount++) {
BSONObj nextDoc;
PlanExecutor::ExecState state = exec->getNext(&nextDoc, nullptr);
@@ -199,16 +211,26 @@ public:
invariant(state == PlanExecutor::ADVANCED);
// If we can't fit this result inside the current batch, then we stash it for later.
- if (!FindCommon::haveSpaceForNext(nextDoc, objCount, firstBatch.len())) {
+ if (!FindCommon::haveSpaceForNext(nextDoc, objCount, bytesBuffered)) {
exec->enqueue(nextDoc);
break;
}
- firstBatch.append(nextDoc);
+ try {
+ firstBatch.push_back(ListIndexesReplyItem::parse(
+ IDLParserErrorContext("ListIndexesReplyItem"), nextDoc));
+ } catch (const DBException& exc) {
+ LOGV2_ERROR(5254500,
+ "Could not parse catalog entry while replying to listIndexes",
+ "entry"_attr = nextDoc,
+ "error"_attr = exc);
+ fassertFailed(5254501);
+ }
+ bytesBuffered += nextDoc.objsize();
}
if (exec->isEOF()) {
- appendCursorResponseObject(0LL, nss.ns(), firstBatch.arr(), &result);
+ appendListIndexesCursorReply(0 /* cursorId */, nss, std::move(firstBatch), result);
return true;
}
@@ -228,8 +250,8 @@ public:
cmdObj,
{Privilege(ResourcePattern::forExactNamespace(nss), ActionType::listIndexes)}});
- appendCursorResponseObject(
- pinnedCursor.getCursor()->cursorid(), nss.ns(), firstBatch.arr(), &result);
+ appendListIndexesCursorReply(
+ pinnedCursor.getCursor()->cursorid(), nss, std::move(firstBatch), result);
return true;
}
diff --git a/src/mongo/db/create_indexes.idl b/src/mongo/db/create_indexes.idl
index 20b589660ca..d9a58ba026e 100644
--- a/src/mongo/db/create_indexes.idl
+++ b/src/mongo/db/create_indexes.idl
@@ -38,35 +38,45 @@ imports:
structs:
+ # A built index appears with these fields, which must be the same as ListIndexReplyItem's fields
+ # in list_indexes.idl.
+ # TODO (SERVER-52539): Write a test that asserts they're the same.
NewIndexSpec:
description: "A type representing a spec for a new index"
strict: true
fields:
- key: object
+ v:
+ type: safeInt
+ optional: true
+ key: object_owned
name: string
+ ns:
+ # MongoDB 4.2 and older generate this field, see SERVER-41696.
+ type: string
+ ignore: true
background:
- type: bool
+ type: safeBool
optional: true
unique:
- type: bool
+ type: safeBool
optional: true
hidden:
- type: bool
+ type: safeBool
optional: true
partialFilterExpression:
- type: object
+ type: object_owned
optional: true
sparse:
- type: bool
+ type: safeBool
optional: true
expireAfterSeconds:
- type: int
+ type: safeInt
optional: true
storageEngine:
- type: object
+ type: object_owned
optional: true
weights:
- type: object
+ type: object_owned
optional: true
default_language:
type: string
@@ -75,26 +85,39 @@ structs:
type: string
optional: true
textIndexVersion:
- type: int
+ type: safeInt
optional: true
2dsphereIndexVersion:
- type: int
+ type: safeInt
optional: true
bits:
- type: int
+ type: safeInt
optional: true
min:
- type: double
+ type: safeDouble
optional: true
max:
- type: double
+ type: safeDouble
optional: true
bucketSize:
- type: double
+ type: safeDouble
optional: true
collation:
- type: object
+ type: object_owned
+ optional: true
+ wildcardProjection:
+ type: object_owned
+ optional: true
+ coarsestIndexedLevel:
+ type: safeInt
+ optional: true
+ finestIndexedLevel:
+ type: safeInt
+ optional: true
+ dropDups:
+ type: safeBool
optional: true
+ unstable: true
CreateIndexesCmd:
description: "A struct representing a createIndexes command"
diff --git a/src/mongo/db/list_indexes.idl b/src/mongo/db/list_indexes.idl
new file mode 100644
index 00000000000..81b592c9a10
--- /dev/null
+++ b/src/mongo/db/list_indexes.idl
@@ -0,0 +1,167 @@
+# Copyright (C) 2020-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.
+#
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/util/uuid.h"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+ - "mongo/db/create_indexes.idl"
+
+structs:
+ ListIndexesReplyItem:
+ description: "An item in the listIndexes command's reply"
+ fields:
+ #
+ # A built index appears with these fields, which must be the same as NewIndexSpec's
+ # fields. The "key" and "name" fields are required for built indexes, but marked
+ # optional to allow the in-progress index build format using the fields below.
+ #
+ v:
+ type: safeInt
+ optional: true
+ key:
+ type: object_owned
+ optional: true
+ name:
+ type: string
+ optional: true
+ ns:
+ # MongoDB 4.2 and older generate this field, see SERVER-41696.
+ type: string
+ ignore: true
+ background:
+ type: safeBool
+ optional: true
+ unique:
+ type: safeBool
+ optional: true
+ hidden:
+ type: safeBool
+ optional: true
+ partialFilterExpression:
+ type: object_owned
+ optional: true
+ sparse:
+ type: safeBool
+ optional: true
+ expireAfterSeconds:
+ type: safeInt
+ optional: true
+ storageEngine:
+ type: object_owned
+ optional: true
+ weights:
+ type: object_owned
+ optional: true
+ default_language:
+ type: string
+ optional: true
+ language_override:
+ type: string
+ optional: true
+ textIndexVersion:
+ type: safeInt
+ optional: true
+ 2dsphereIndexVersion:
+ type: safeInt
+ optional: true
+ bits:
+ type: safeInt
+ optional: true
+ min:
+ type: safeDouble
+ optional: true
+ max:
+ type: safeDouble
+ optional: true
+ bucketSize:
+ type: safeDouble
+ optional: true
+ collation:
+ type: object_owned
+ optional: true
+ wildcardProjection:
+ type: object_owned
+ optional: true
+ coarsestIndexedLevel:
+ type: safeInt
+ optional: true
+ finestIndexedLevel:
+ type: safeInt
+ optional: true
+ dropDups:
+ type: safeBool
+ optional: true
+ #
+ # An index build in progress appears with these two fields. They're required, but marked
+ # optional to permit the built index format using the fields above instead.
+ #
+ buildUUID:
+ type: uuid
+ optional: true
+ spec:
+ type: NewIndexSpec
+ optional: true
+
+ ListIndexesReplyCursor:
+ description: "Cursor object"
+ fields:
+ id: long
+ ns: namespacestring
+ firstBatch: array<ListIndexesReplyItem>
+
+ ListIndexesReply:
+ description: "The listIndexes command's reply."
+ fields:
+ cursor: ListIndexesReplyCursor
+ # Included so mongos can parse shards' listIndexes replies.
+ ok:
+ type: safeDouble
+ validator: { gte: 0.0, lte: 1.0 }
+ optional: true
+
+commands:
+ listIndexes:
+ description: "Parser for the listIndexes command"
+ command_name: listIndexes
+ namespace: concatenate_with_db_or_uuid
+ cpp_name: listIndexes
+ strict: true
+ api_version: "1"
+ fields:
+ cursor:
+ type: SimpleCursorOptions
+ optional: true
+ includeBuildUUIDs:
+ type: safeBool
+ unstable: true
+ default: false
+ reply_type: ListIndexesReply
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp
index 19b0fc0b720..d6ff9610264 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_config_initialization_test.cpp
@@ -64,10 +64,13 @@ void assertBSONObjsSame(const std::vector<BSONObj>& expectedBSON,
const std::vector<BSONObj>& foundBSON) {
ASSERT_EQUALS(expectedBSON.size(), foundBSON.size());
+ auto flags =
+ BSONObj::ComparisonRules::kIgnoreFieldOrder | BSONObj::ComparisonRules::kConsiderFieldName;
+
for (const auto& expectedObj : expectedBSON) {
bool wasFound = false;
for (const auto& foundObj : foundBSON) {
- if (expectedObj.woCompare(foundObj) == 0) {
+ if (expectedObj.woCompare(foundObj, {}, flags) == 0) {
wasFound = true;
break;
}
diff --git a/src/mongo/db/timeseries/timeseries.idl b/src/mongo/db/timeseries/timeseries.idl
index c2ecaf9227b..814bb634b65 100644
--- a/src/mongo/db/timeseries/timeseries.idl
+++ b/src/mongo/db/timeseries/timeseries.idl
@@ -50,5 +50,5 @@ structs:
expireAfterSeconds:
description: "The number of seconds after which old time-series data should be
deleted."
- type: long
+ type: safeInt64
optional: true
diff --git a/src/mongo/idl/basic_types.idl b/src/mongo/idl/basic_types.idl
index 6352fa9d4ab..a52fc202fe2 100644
--- a/src/mongo/idl/basic_types.idl
+++ b/src/mongo/idl/basic_types.idl
@@ -47,6 +47,16 @@ types:
cpp_type: "std::int32_t"
deserializer: "mongo::BSONElement::_numberInt"
+ safeInt:
+ bson_serialization_type:
+ - long
+ - int
+ - decimal
+ - double
+ description: "Accepts any numerical type within integer range"
+ cpp_type: "std::int32_t"
+ deserializer: "mongo::BSONElement::safeNumberInt"
+
safeInt64:
bson_serialization_type:
- long
diff --git a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
index 79bc042a0d7..8786050d801 100644
--- a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
+#include "mongo/db/list_indexes_gen.h"
#include "mongo/s/cluster_commands_helpers.h"
#include "mongo/s/query/store_possible_cursor.h"
@@ -65,6 +66,8 @@ bool cursorCommandPassthroughShardWithMinKeyChunk(OperationContext* opCtx,
privileges));
CommandHelpers::filterCommandReplyForPassthrough(transformedResponse, out);
+ // The reply syntax must conform to its IDL definition.
+ ListIndexesReply::parse({"listIndexes"}, out->asTempObj());
return true;
}
@@ -119,7 +122,10 @@ public:
const BSONObj& cmdObj,
BSONObjBuilder& result) override {
CommandHelpers::handleMarkKillOnClientDisconnect(opCtx);
+ // Check the command syntax before passing to shard.
+ const auto parsed = ListIndexes::parse({"listIndexes"}, cmdObj);
+ // The command's IDL definition permits namespace or UUID, but mongos requires a namespace.
const NamespaceString nss(parseNs(dbName, cmdObj));
const auto cm =
uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss));
diff --git a/src/mongo/scripting/mozjs/bson.cpp b/src/mongo/scripting/mozjs/bson.cpp
index 0585022615a..efe78d2feab 100644
--- a/src/mongo/scripting/mozjs/bson.cpp
+++ b/src/mongo/scripting/mozjs/bson.cpp
@@ -31,6 +31,7 @@
#include "mongo/scripting/mozjs/bson.h"
#include <boost/optional.hpp>
+#include <fmt/format.h>
#include <set>
#include "mongo/scripting/mozjs/idwrapper.h"
@@ -44,10 +45,13 @@
namespace mongo {
namespace mozjs {
+using namespace fmt::literals;
+
const char* const BSONInfo::className = "BSON";
-const JSFunctionSpec BSONInfo::freeFunctions[4] = {
+const JSFunctionSpec BSONInfo::freeFunctions[5] = {
MONGO_ATTACH_JS_FUNCTION(bsonWoCompare),
+ MONGO_ATTACH_JS_FUNCTION(bsonUnorderedFieldsCompare),
MONGO_ATTACH_JS_FUNCTION(bsonBinaryEqual),
MONGO_ATTACH_JS_FUNCTION(bsonObjToArray),
JS_FS_END,
@@ -276,9 +280,13 @@ void BSONInfo::Functions::bsonObjToArray::call(JSContext* cx, JS::CallArgs args)
ValueReader(cx, args.rval()).fromBSONArray(obj, nullptr, false);
}
-void BSONInfo::Functions::bsonWoCompare::call(JSContext* cx, JS::CallArgs args) {
+namespace {
+void bsonCompareCommon(JSContext* cx,
+ JS::CallArgs args,
+ StringData funcName,
+ BSONObj::ComparisonRulesSet rules) {
if (args.length() != 2)
- uasserted(ErrorCodes::BadValue, "bsonWoCompare needs 2 arguments");
+ uasserted(ErrorCodes::BadValue, "{} needs 2 arguments"_format(funcName));
// If either argument is not proper BSON, then we wrap both objects.
auto scope = getScope(cx);
@@ -288,7 +296,20 @@ void BSONInfo::Functions::bsonWoCompare::call(JSContext* cx, JS::CallArgs args)
BSONObj bsonObject1 = getBSONFromArg(cx, args.get(0), isBSON);
BSONObj bsonObject2 = getBSONFromArg(cx, args.get(1), isBSON);
- args.rval().setInt32(bsonObject1.woCompare(bsonObject2));
+ args.rval().setInt32(bsonObject1.woCompare(bsonObject2, {}, rules));
+}
+} // namespace
+
+void BSONInfo::Functions::bsonWoCompare::call(JSContext* cx, JS::CallArgs args) {
+ bsonCompareCommon(cx, args, "bsonWoCompare", BSONObj::ComparatorInterface::kConsiderFieldName);
+}
+
+void BSONInfo::Functions::bsonUnorderedFieldsCompare::call(JSContext* cx, JS::CallArgs args) {
+ bsonCompareCommon(cx,
+ args,
+ "bsonWoCompare",
+ BSONObj::ComparatorInterface::kConsiderFieldName |
+ BSONObj::ComparatorInterface::kIgnoreFieldOrder);
}
void BSONInfo::Functions::bsonBinaryEqual::call(JSContext* cx, JS::CallArgs args) {
diff --git a/src/mongo/scripting/mozjs/bson.h b/src/mongo/scripting/mozjs/bson.h
index f515c4fd32a..a2cc5f1d2d3 100644
--- a/src/mongo/scripting/mozjs/bson.h
+++ b/src/mongo/scripting/mozjs/bson.h
@@ -72,11 +72,12 @@ struct BSONInfo : public BaseInfo {
struct Functions {
MONGO_DECLARE_JS_FUNCTION(bsonWoCompare);
+ MONGO_DECLARE_JS_FUNCTION(bsonUnorderedFieldsCompare);
MONGO_DECLARE_JS_FUNCTION(bsonBinaryEqual);
MONGO_DECLARE_JS_FUNCTION(bsonObjToArray);
};
- static const JSFunctionSpec freeFunctions[4];
+ static const JSFunctionSpec freeFunctions[5];
static std::tuple<BSONObj*, bool> originalBSON(JSContext* cx, JS::HandleObject obj);
static void make(