summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog/index_key_validate.cpp
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2016-09-01 12:15:34 -0400
committerMax Hirschhorn <max.hirschhorn@mongodb.com>2016-09-01 12:15:34 -0400
commit159d4db49c2aa2ecfc988e25999ee780f53a5efd (patch)
tree5ba91ca426ad3f6f584aa57de608f31753f62a5a /src/mongo/db/catalog/index_key_validate.cpp
parentaf2b6a08feb822b3ce9644ee6f45a4731d868ad5 (diff)
downloadmongo-159d4db49c2aa2ecfc988e25999ee780f53a5efd.tar.gz
SERVER-25156 Define a validateIndexSpec() helper function.
Consolidates and moves some of the option parsing in the "createIndexes" command to its own library so that it can be unit tested.
Diffstat (limited to 'src/mongo/db/catalog/index_key_validate.cpp')
-rw-r--r--src/mongo/db/catalog/index_key_validate.cpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/mongo/db/catalog/index_key_validate.cpp b/src/mongo/db/catalog/index_key_validate.cpp
index 4c692f98f37..758524007c0 100644
--- a/src/mongo/db/catalog/index_key_validate.cpp
+++ b/src/mongo/db/catalog/index_key_validate.cpp
@@ -33,15 +33,26 @@
#include <cmath>
#include <limits>
+#include "mongo/base/status.h"
+#include "mongo/base/status_with.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/index_names.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/namespace_string.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
using std::string;
+namespace {
+const int kIndexVersionV0 = 0;
+
+const StringData kKeyPatternFieldName = "key"_sd;
+const StringData kNamespaceFieldName = "ns"_sd;
+const StringData kVersionFieldName = "v"_sd;
+} // namespace
+
Status validateKeyPattern(const BSONObj& key) {
const ErrorCodes::Error code = ErrorCodes::CannotCreateIndex;
@@ -129,4 +140,97 @@ Status validateKeyPattern(const BSONObj& key) {
return Status::OK();
}
+
+StatusWith<BSONObj> validateIndexSpec(const BSONObj& indexSpec,
+ const NamespaceString& expectedNamespace) {
+ bool hasKeyPatternField = false;
+ bool hasNamespaceField = false;
+
+ for (auto&& indexSpecElem : indexSpec) {
+ auto indexSpecElemFieldName = indexSpecElem.fieldNameStringData();
+ if (kKeyPatternFieldName == indexSpecElemFieldName) {
+ if (indexSpecElem.type() != BSONType::Object) {
+ return {ErrorCodes::TypeMismatch,
+ str::stream() << "The field '" << kKeyPatternFieldName
+ << "' must be an object, but got "
+ << typeName(indexSpecElem.type())};
+ }
+
+ std::vector<StringData> keys;
+ for (auto&& keyElem : indexSpecElem.Obj()) {
+ auto keyElemFieldName = keyElem.fieldNameStringData();
+ if (std::find(keys.begin(), keys.end(), keyElemFieldName) != keys.end()) {
+ return {ErrorCodes::BadValue,
+ str::stream() << "The field '" << keyElemFieldName
+ << "' appears multiple times in the index key pattern "
+ << indexSpecElem.Obj()};
+ }
+ keys.push_back(keyElemFieldName);
+ }
+
+ hasKeyPatternField = true;
+ } else if (kNamespaceFieldName == indexSpecElemFieldName) {
+ if (indexSpecElem.type() != BSONType::String) {
+ return {ErrorCodes::TypeMismatch,
+ str::stream() << "The field '" << kNamespaceFieldName
+ << "' must be a string, but got "
+ << typeName(indexSpecElem.type())};
+ }
+
+ StringData ns = indexSpecElem.valueStringData();
+ if (ns.empty()) {
+ return {ErrorCodes::BadValue,
+ str::stream() << "The field '" << kNamespaceFieldName
+ << "' cannot be an empty string"};
+ }
+
+ if (ns != expectedNamespace.ns()) {
+ return {ErrorCodes::BadValue,
+ str::stream() << "The value of the field '" << kNamespaceFieldName << "' ("
+ << ns
+ << ") doesn't match the namespace '"
+ << expectedNamespace.ns()
+ << "'"};
+ }
+
+ hasNamespaceField = true;
+ } else if (kVersionFieldName == indexSpecElemFieldName) {
+ if (!indexSpecElem.isNumber()) {
+ return {ErrorCodes::TypeMismatch,
+ str::stream() << "The field '" << kVersionFieldName
+ << "' must be a number, but got "
+ << typeName(indexSpecElem.type())};
+ }
+
+ if (kIndexVersionV0 == indexSpecElem.numberInt()) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "Invalid index specification " << indexSpec
+ << "; cannot create an index with "
+ << kVersionFieldName
+ << "="
+ << kIndexVersionV0};
+ }
+ } else {
+ // TODO SERVER-769: Validate index options specified in the "createIndexes" command.
+ continue;
+ }
+ }
+
+ if (!hasKeyPatternField) {
+ return {ErrorCodes::FailedToParse,
+ str::stream() << "The '" << kKeyPatternFieldName
+ << "' field is a required property of an index specification"};
+ }
+
+ if (!hasNamespaceField) {
+ // We create a new index specification with the 'ns' field set as 'expectedNamespace' if the
+ // field was omitted.
+ BSONObjBuilder bob;
+ bob.append(kNamespaceFieldName, expectedNamespace.ns());
+ bob.appendElements(indexSpec);
+ return bob.obj();
+ }
+
+ return indexSpec;
+}
} // namespace mongo