summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-04-02 21:36:01 -0400
committerGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-04-02 21:38:45 -0400
commit24aa7dc8f39e133da8a3e405863e5dbbd980f68d (patch)
tree2f6036aad918f29be82fe2e6831e2453fe679446 /src/mongo/db/commands
parent573495bbf17851758e7fcf76c85a3d66d6b53342 (diff)
downloadmongo-24aa7dc8f39e133da8a3e405863e5dbbd980f68d.tar.gz
SERVER-39231 'create' command should reject incorrect types for known options
Diffstat (limited to 'src/mongo/db/commands')
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/create.idl117
-rw-r--r--src/mongo/db/commands/dbcommands.cpp83
3 files changed, 173 insertions, 28 deletions
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index c1faa282b74..b3c753cf933 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -259,6 +259,7 @@ env.Library(
"sleep_command.cpp",
"validate.cpp",
"write_commands/write_commands.cpp",
+ env.Idlc('create.idl')[0],
env.Idlc('enable_coordinator_for_create_indexes_command.idl')[0],
],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/db/commands/create.idl b/src/mongo/db/commands/create.idl
new file mode 100644
index 00000000000..685b56f483a
--- /dev/null
+++ b/src/mongo/db/commands/create.idl
@@ -0,0 +1,117 @@
+# Copyright (C) 2019-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"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+commands:
+ create:
+ description: "Parser for the 'create' Command"
+ namespace: concatenate_with_db
+ cpp_name: CreateCommand
+ strict: true
+ fields:
+ capped:
+ description: "Specify true to create a capped collection. If you specify true, you
+ must also set a maximum size in the 'size' field."
+ type: safeBool
+ default: false
+ autoIndexId:
+ description: "Specify false to disable the automatic creation of an index on the
+ _id field."
+ type: safeBool
+ optional: true
+ idIndex:
+ description: "Specify the default _id index specification."
+ type: object
+ optional: true
+ size:
+ description: "Specify a maximum size in bytes for the capped collection."
+ type: safeInt64
+ optional: true
+ max:
+ description: "The maximum number of documents allowed in the capped collection. The
+ 'size' limit takes precedence over this limit."
+ type: safeInt64
+ optional: true
+ storageEngine:
+ description: "Specify a configuration to the storage engine on a per-collection
+ basis when creating a collection."
+ type: object
+ optional: true
+ validator:
+ description: "Specify validation rules or expressions for the collection."
+ type: object
+ optional: true
+ validationLevel:
+ description: "Determines how strictly to apply the validation rules to existing
+ documents during an update.
+ Can be one of following values: 'off', 'strict' or 'moderate'."
+ type: string
+ default: '"strict"'
+ validationAction:
+ description: "Determines whether to error on invalid documents or just warn about
+ the violations but allow invalid documents to be inserted.
+ Can be either 'warn' or 'error'."
+ type: string
+ default: '"error"'
+ indexOptionDefaults:
+ description: "Allows users to specify a default configuration for indexes when
+ creating a collection."
+ type: object
+ optional: true
+ viewOn:
+ description: "The name of the source collection or view from which to create the
+ view."
+ type: string
+ optional: true
+ pipeline:
+ description: "An array that consists of the aggregation pipeline. Creates the view
+ by applying the specified pipeline to the 'viewOn' collection or
+ view."
+ type: array<object>
+ optional: true
+ collation:
+ description: "Specifies the default collation for the collection or the view."
+ type: object
+ optional: true
+ writeConcern:
+ description: "A document that expresses the write concern for the operation."
+ type: object
+ optional: true
+ temp:
+ description: "DEPRECATED"
+ type: safeBool
+ optional: true
+ flags:
+ description: "DEPRECATED"
+ type: int
+ optional: true
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 7378c1fae2c..1be49d127e4 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -55,6 +55,7 @@
#include "mongo/db/catalog_raii.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
+#include "mongo/db/commands/create_gen.h"
#include "mongo/db/commands/profile_common.h"
#include "mongo/db/commands/profile_gen.h"
#include "mongo/db/commands/server_status.h"
@@ -259,22 +260,41 @@ public:
class CmdCreate : public BasicCommand {
public:
CmdCreate() : BasicCommand("create") {}
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
+
virtual bool adminOnly() const {
return false;
}
-
virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
return true;
}
std::string help() const override {
- return "create a collection explicitly\n"
- "{ create: <ns>[, capped: <bool>, size: <collSizeInBytes>, max: <nDocs>] }";
+ return str::stream()
+ << "explicitly creates a collection or view\n"
+ << "{\n"
+ << " create: <string: collection or view name> [,\n"
+ << " capped: <bool: capped collection>,\n"
+ << " autoIndexId: <bool: automatic creation of _id index>,\n"
+ << " idIndex: <document: _id index specification>,\n"
+ << " size: <int: size in bytes of the capped collection>,\n"
+ << " max: <int: max number of documents in the capped collection>,\n"
+ << " storageEngine: <document: storage engine configuration>,\n"
+ << " validator: <document: validation rules>,\n"
+ << " validationLevel: <string: validation level>,\n"
+ << " validationAction: <string: validation action>,\n"
+ << " indexOptionDefaults: <document: default configuration for indexes>,\n"
+ << " viewOn: <string: name of source collection or view>,\n"
+ << " pipeline: <array<object>: aggregation pipeline stage>,\n"
+ << " collation: <document: default collation for the collection or view>,\n"
+ << " writeConcern: <document: write concern expression for the operation>]\n"
+ << "}";
}
+
virtual Status checkAuthForCommand(Client* client,
const std::string& dbname,
const BSONObj& cmdObj) const {
@@ -286,34 +306,44 @@ public:
const string& dbname,
const BSONObj& cmdObj,
BSONObjBuilder& result) {
- const NamespaceString ns(CommandHelpers::parseNsCollectionRequired(dbname, cmdObj));
+ IDLParserErrorContext ctx("create");
+ CreateCommand cmd = CreateCommand::parse(ctx, cmdObj);
- if (cmdObj.hasField("autoIndexId")) {
+ const NamespaceString ns = cmd.getNamespace();
+
+ if (cmd.getAutoIndexId()) {
const char* deprecationWarning =
"the autoIndexId option is deprecated and will be removed in a future release";
warning() << deprecationWarning;
result.append("note", deprecationWarning);
}
+ // Ensure that the 'size' field is present if 'capped' is set to true.
+ if (cmd.getCapped()) {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "the 'size' field is required when 'capped' is true",
+ cmd.getSize());
+ }
+
+ // If the 'size' or 'max' fields are present, then 'capped' must be set to true.
+ if (cmd.getSize() || cmd.getMax()) {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "the 'capped' field needs to be true when either the 'size'"
+ << " or 'max' fields are present",
+ cmd.getCapped());
+ }
+
// Validate _id index spec and fill in missing fields.
- if (auto idIndexElem = cmdObj["idIndex"]) {
- if (cmdObj["viewOn"]) {
- uasserted(ErrorCodes::InvalidOptions,
- str::stream() << "'idIndex' is not allowed with 'viewOn': "
- << idIndexElem);
- }
- if (cmdObj["autoIndexId"]) {
- uasserted(ErrorCodes::InvalidOptions,
- str::stream() << "'idIndex' is not allowed with 'autoIndexId': "
- << idIndexElem);
- }
+ if (cmd.getIdIndex()) {
+ auto idIndexSpec = *cmd.getIdIndex();
- if (idIndexElem.type() != BSONType::Object) {
- uasserted(ErrorCodes::TypeMismatch,
- str::stream() << "'idIndex' has to be a document: " << idIndexElem);
- }
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'idIndex' is not allowed with 'viewOn': " << idIndexSpec,
+ !cmd.getViewOn());
- auto idIndexSpec = idIndexElem.Obj();
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'idIndex' is not allowed with 'autoIndexId': " << idIndexSpec,
+ !cmd.getAutoIndexId());
// Perform index spec validation.
idIndexSpec = uassertStatusOK(index_key_validate::validateIndexSpec(
@@ -322,19 +352,16 @@ public:
// Validate or fill in _id index collation.
std::unique_ptr<CollatorInterface> defaultCollator;
- if (auto collationElem = cmdObj["collation"]) {
- if (collationElem.type() != BSONType::Object) {
- uasserted(ErrorCodes::TypeMismatch,
- str::stream() << "'collation' has to be a document: "
- << collationElem);
- }
+ if (cmd.getCollation()) {
auto collatorStatus = CollatorFactoryInterface::get(opCtx->getServiceContext())
- ->makeFromBSON(collationElem.Obj());
+ ->makeFromBSON(*cmd.getCollation());
uassertStatusOK(collatorStatus.getStatus());
defaultCollator = std::move(collatorStatus.getValue());
}
+
idIndexSpec = uassertStatusOK(index_key_validate::validateIndexSpecCollation(
opCtx, idIndexSpec, defaultCollator.get()));
+
std::unique_ptr<CollatorInterface> idIndexCollator;
if (auto collationElem = idIndexSpec["collation"]) {
auto collatorStatus = CollatorFactoryInterface::get(opCtx->getServiceContext())