diff options
author | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-09-07 17:37:46 -0400 |
---|---|---|
committer | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-09-07 17:37:46 -0400 |
commit | 071065a2969176ad2aa2ac9c3210e5fa9410cea6 (patch) | |
tree | 0e77b2ace8c9507bcd95a3b6c0dd73e347bcef1b /src/mongo/db/catalog/index_key_validate.cpp | |
parent | 5133e213c79378893f6bc7671e57789e1f6a9874 (diff) | |
download | mongo-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.cpp | 84 |
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(); } |