summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavis Haupt <davis.haupt@mongodb.com>2022-01-06 22:17:46 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-06 23:18:25 +0000
commit0a1a88755daa504c67e13dd49667a06c3c606ee8 (patch)
tree5a0b162cf0d0773083b416e80ee06f9251617686
parent9ce5ff8c50813185e3c7c4351ca775461022ca0e (diff)
downloadmongo-0a1a88755daa504c67e13dd49667a06c3c606ee8.tar.gz
SERVER-58358 validate arguments passed to dataSize command
-rw-r--r--jstests/core/datasize_validation.js53
-rw-r--r--src/mongo/db/commands/dbcommands.cpp18
2 files changed, 70 insertions, 1 deletions
diff --git a/jstests/core/datasize_validation.js b/jstests/core/datasize_validation.js
new file mode 100644
index 00000000000..c0f9c9d67b2
--- /dev/null
+++ b/jstests/core/datasize_validation.js
@@ -0,0 +1,53 @@
+// Cannot implicitly shard accessed collections because the "dataSize" command returns an
+// "keyPattern must equal shard key" error response.
+// @tags: [assumes_unsharded_collection, requires_fcv_53]
+
+//
+// Test argument validation for dataSize command
+//
+
+(function() {
+let coll = db[jsTestName()];
+coll.drop();
+coll.insertOne({_id: 1});
+coll.insertOne({_id: 2});
+coll.insertOne({_id: 3});
+coll.insertOne({_id: 4});
+
+assert.commandFailed(db.runCommand({
+ 'dataSize': coll.getFullName(),
+ min: NumberLong("1"),
+ max: NumberLong("2"),
+ estimate: false
+}),
+ "min and max should be objects");
+
+assert.commandFailed(
+ db.runCommand({'dataSize': coll.getFullName(), min: {_id: NumberLong("1")}, estimate: false}),
+ "min and max should both be present");
+assert.commandFailed(
+ db.runCommand({'dataSize': coll.getFullName(), max: {_id: NumberLong("2")}, estimate: false}),
+ "min and max should both be present");
+
+let resultWithKey = assert.commandWorked(db.runCommand({
+ 'dataSize': coll.getFullName(),
+ keyPattern: {_id: 1},
+ min: {_id: NumberLong("1")},
+ max: {_id: NumberLong("2")},
+ estimate: false
+}));
+assert.eq(1, resultWithKey.numObjects, "only 1 object should be inspected between min/max bounds.");
+
+let result = assert.commandWorked(db.runCommand({
+ 'dataSize': coll.getFullName(),
+ min: {_id: NumberLong("1")},
+ max: {_id: NumberLong("2")},
+ estimate: false
+}));
+assert.eq(result.size,
+ resultWithKey.size,
+ "measured size should be equal after keyPattern properly inferred from min/max bounds.");
+assert.eq(result.numObjects,
+ resultWithKey.numObjects,
+ "numObjects should be equal after keyPattern properly inferred from min/max bounds.");
+})();
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 9167dc0d18e..1addfe77936 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -304,8 +304,24 @@ public:
const BSONObj& jsobj,
std::string& errmsg,
BSONObjBuilder& result) override {
- Timer timer;
+ auto hasMin = jsobj.hasField("min");
+ auto hasMax = jsobj.hasField("max");
+
+ uassert(ErrorCodes::BadValue,
+ hasMin ? "max must be set if min is set" : "min must be set if max is set",
+ hasMin == hasMax);
+
+ if (hasMin) {
+ uassert(ErrorCodes::BadValue,
+ "min key must be an object",
+ jsobj["min"].type() == BSONType::Object);
+ uassert(ErrorCodes::BadValue,
+ "max key must be an object",
+ jsobj["max"].type() == BSONType::Object);
+ }
+
+ Timer timer;
std::string ns = jsobj.firstElement().String();
BSONObj min = jsobj.getObjectField("min");
BSONObj max = jsobj.getObjectField("max");