summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog/index_key_validate.cpp
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2016-09-07 17:37:46 -0400
committerMax Hirschhorn <max.hirschhorn@mongodb.com>2016-09-07 17:37:46 -0400
commit071065a2969176ad2aa2ac9c3210e5fa9410cea6 (patch)
tree0e77b2ace8c9507bcd95a3b6c0dd73e347bcef1b /src/mongo/db/catalog/index_key_validate.cpp
parent5133e213c79378893f6bc7671e57789e1f6a9874 (diff)
downloadmongo-071065a2969176ad2aa2ac9c3210e5fa9410cea6.tar.gz
SERVER-25156 Add support for building v=2 indexes.
We use index version v=2 as the default index version when the featureCompatibilityVersion is 3.4, and we use index version v=1 as the default index version when the featureCompatibilityVersion is 3.2. The "collation" index option can only be used with v=2 indexes.
Diffstat (limited to 'src/mongo/db/catalog/index_key_validate.cpp')
-rw-r--r--src/mongo/db/catalog/index_key_validate.cpp84
1 files changed, 69 insertions, 15 deletions
diff --git a/src/mongo/db/catalog/index_key_validate.cpp b/src/mongo/db/catalog/index_key_validate.cpp
index 758524007c0..44c2db2d5e7 100644
--- a/src/mongo/db/catalog/index_key_validate.cpp
+++ b/src/mongo/db/catalog/index_key_validate.cpp
@@ -30,27 +30,31 @@
#include "mongo/db/catalog/index_key_validate.h"
+#include <boost/optional.hpp>
#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/index_descriptor.h"
#include "mongo/db/index_names.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/represent_as.h"
namespace mongo {
using std::string;
-namespace {
-const int kIndexVersionV0 = 0;
+using IndexVersion = IndexDescriptor::IndexVersion;
+namespace {
const StringData kKeyPatternFieldName = "key"_sd;
const StringData kNamespaceFieldName = "ns"_sd;
const StringData kVersionFieldName = "v"_sd;
+const StringData kCollationFieldName = "collation"_sd;
} // namespace
Status validateKeyPattern(const BSONObj& key) {
@@ -141,10 +145,16 @@ Status validateKeyPattern(const BSONObj& key) {
return Status::OK();
}
-StatusWith<BSONObj> validateIndexSpec(const BSONObj& indexSpec,
- const NamespaceString& expectedNamespace) {
+StatusWith<BSONObj> validateIndexSpec(
+ const BSONObj& indexSpec,
+ const NamespaceString& expectedNamespace,
+ ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) {
bool hasKeyPatternField = false;
bool hasNamespaceField = false;
+ bool hasVersionField = false;
+ bool hasCollationField = false;
+
+ boost::optional<IndexVersion> resolvedIndexVersion;
for (auto&& indexSpecElem : indexSpec) {
auto indexSpecElemFieldName = indexSpecElem.fieldNameStringData();
@@ -202,31 +212,75 @@ StatusWith<BSONObj> validateIndexSpec(const BSONObj& indexSpec,
<< typeName(indexSpecElem.type())};
}
- if (kIndexVersionV0 == indexSpecElem.numberInt()) {
- return {ErrorCodes::CannotCreateIndex,
- str::stream() << "Invalid index specification " << indexSpec
- << "; cannot create an index with "
- << kVersionFieldName
- << "="
- << kIndexVersionV0};
+ auto requestedIndexVersionAsInt = representAs<int>(indexSpecElem.number());
+ if (!requestedIndexVersionAsInt) {
+ return {ErrorCodes::BadValue,
+ str::stream()
+ << "Index version must be representable as a 32-bit integer, but got "
+ << indexSpecElem.toString(false, false)};
+ }
+
+ const IndexVersion requestedIndexVersion =
+ static_cast<IndexVersion>(*requestedIndexVersionAsInt);
+ auto creationAllowedStatus = IndexDescriptor::isIndexVersionAllowedForCreation(
+ requestedIndexVersion, featureCompatibilityVersion, indexSpec);
+ if (!creationAllowedStatus.isOK()) {
+ return creationAllowedStatus;
}
+
+ hasVersionField = true;
+ resolvedIndexVersion = requestedIndexVersion;
+ } else if (kCollationFieldName == indexSpecElemFieldName) {
+ if (indexSpecElem.type() != BSONType::Object) {
+ return {ErrorCodes::TypeMismatch,
+ str::stream() << "The field '" << kNamespaceFieldName
+ << "' must be an object, but got "
+ << typeName(indexSpecElem.type())};
+ }
+
+ hasCollationField = true;
} else {
// TODO SERVER-769: Validate index options specified in the "createIndexes" command.
continue;
}
}
+ if (!resolvedIndexVersion) {
+ resolvedIndexVersion = IndexDescriptor::getDefaultIndexVersion(featureCompatibilityVersion);
+ }
+
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.
+ if (hasCollationField && *resolvedIndexVersion < IndexVersion::kV2) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "Invalid index specification " << indexSpec
+ << "; cannot create an index with the '"
+ << kCollationFieldName
+ << "' option and "
+ << kVersionFieldName
+ << "="
+ << static_cast<int>(*resolvedIndexVersion)};
+ }
+
+ if (!hasNamespaceField || !hasVersionField) {
BSONObjBuilder bob;
- bob.append(kNamespaceFieldName, expectedNamespace.ns());
+
+ if (!hasNamespaceField) {
+ // We create a new index specification with the 'ns' field set as 'expectedNamespace' if
+ // the field was omitted.
+ bob.append(kNamespaceFieldName, expectedNamespace.ns());
+ }
+
+ if (!hasVersionField) {
+ // We create a new index specification with the 'v' field set as 'defaultIndexVersion'
+ // if the field was omitted.
+ bob.append(kVersionFieldName, static_cast<int>(*resolvedIndexVersion));
+ }
+
bob.appendElements(indexSpec);
return bob.obj();
}