diff options
author | David Storch <david.storch@10gen.com> | 2016-05-24 15:28:40 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-05-25 14:40:31 -0400 |
commit | 59ca0648a8a7627edb12e160464cf014fd7af07e (patch) | |
tree | 84a55a6b71d6af81a1cb23f262a85a8283315651 /src | |
parent | 439df4c3bdff0194cff402a6268a9bdb9de44a7a (diff) | |
download | mongo-59ca0648a8a7627edb12e160464cf014fd7af07e.tar.gz |
SERVER-23945 make index builds without a collation inherit the collection default
Also ensures that the full BSON representation of the
collation spec associated with an index or with a collection
is materialized in the catalog.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/catalog/collection_options.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_options_test.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/catalog/database.cpp | 24 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog.h | 4 |
5 files changed, 55 insertions, 9 deletions
diff --git a/src/mongo/db/catalog/collection_options.cpp b/src/mongo/db/catalog/collection_options.cpp index 1595706c0e2..b2aa3da4de4 100644 --- a/src/mongo/db/catalog/collection_options.cpp +++ b/src/mongo/db/catalog/collection_options.cpp @@ -215,6 +215,10 @@ Status CollectionOptions::parse(const BSONObj& options) { return Status(ErrorCodes::BadValue, "'collation' has to be a document."); } + if (e.Obj().isEmpty()) { + return Status(ErrorCodes::BadValue, "'collation' cannot be an empty document."); + } + collation = e.Obj().getOwned(); } } diff --git a/src/mongo/db/catalog/collection_options_test.cpp b/src/mongo/db/catalog/collection_options_test.cpp index 85610c6fd02..4e773f1b027 100644 --- a/src/mongo/db/catalog/collection_options_test.cpp +++ b/src/mongo/db/catalog/collection_options_test.cpp @@ -193,6 +193,11 @@ TEST(CollectionOptions, FailToParseCollationThatIsNotAnObject) { ASSERT_NOT_OK(options.parse(fromjson("{collation: 'notAnObject'}"))); } +TEST(CollectionOptions, FailToParseCollationThatIsAnEmptyObject) { + CollectionOptions options; + ASSERT_NOT_OK(options.parse(fromjson("{collation: {}}"))); +} + TEST(CollectionOptions, CollationFieldParsesCorrectly) { CollectionOptions options; ASSERT_OK(options.parse(fromjson("{collation: {locale: 'en'}}"))); diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp index 06e9b8f3933..080d37e0eb8 100644 --- a/src/mongo/db/catalog/database.cpp +++ b/src/mongo/db/catalog/database.cpp @@ -40,27 +40,29 @@ #include "mongo/db/audit.h" #include "mongo/db/auth/auth_index_d.h" #include "mongo/db/background.h" -#include "mongo/db/clientcursor.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/collection_catalog_entry.h" #include "mongo/db/catalog/collection_options.h" #include "mongo/db/catalog/database_catalog_entry.h" #include "mongo/db/catalog/database_holder.h" +#include "mongo/db/clientcursor.h" #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/dbhelpers.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/instance.h" #include "mongo/db/introspect.h" #include "mongo/db/op_observer.h" +#include "mongo/db/query/collation/collation_serializer.h" +#include "mongo/db/query/collation/collator_factory_interface.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/db/server_parameters.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_d.h" #include "mongo/db/stats/top.h" -#include "mongo/db/storage/storage_options.h" -#include "mongo/db/storage/storage_engine.h" #include "mongo/db/storage/recovery_unit.h" +#include "mongo/db/storage/storage_engine.h" +#include "mongo/db/storage/storage_options.h" #include "mongo/util/log.h" namespace mongo { @@ -618,6 +620,18 @@ Status userCreateNS(OperationContext* txn, if (!status.isOK()) return status; + // Validate the collation, if there is one. + if (!collectionOptions.collation.isEmpty()) { + auto collator = CollatorFactoryInterface::get(txn->getServiceContext()) + ->makeFromBSON(collectionOptions.collation); + if (!collator.isOK()) { + return collator.getStatus(); + } + + collectionOptions.collation = + CollationSerializer::specToBSON(collator.getValue()->getSpec()); + } + status = validateStorageOptions(collectionOptions.storageEngine, stdx::bind(&StorageEngine::Factory::validateCollectionStorageOptions, diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp index da3d0553d9f..7887759486b 100644 --- a/src/mongo/db/catalog/index_catalog.cpp +++ b/src/mongo/db/catalog/index_catalog.cpp @@ -57,6 +57,7 @@ #include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/extensions_callback_disallow_extensions.h" #include "mongo/db/ops/delete.h" +#include "mongo/db/query/collation/collation_serializer.h" #include "mongo/db/query/collation/collator_factory_interface.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/replication_coordinator_global.h" @@ -276,7 +277,7 @@ StatusWith<BSONObj> IndexCatalog::prepareSpecForCreate(OperationContext* txn, if (!status.isOK()) return StatusWith<BSONObj>(status); - auto fixed = _fixIndexSpec(original); + auto fixed = _fixIndexSpec(txn, _collection, original); if (!fixed.isOK()) { return fixed; } @@ -1260,7 +1261,9 @@ BSONObj IndexCatalog::fixIndexKey(const BSONObj& key) { return key; } -StatusWith<BSONObj> IndexCatalog::_fixIndexSpec(const BSONObj& spec) { +StatusWith<BSONObj> IndexCatalog::_fixIndexSpec(OperationContext* txn, + Collection* collection, + const BSONObj& spec) { auto statusWithSpec = IndexLegacy::adjustIndexSpecObject(spec); if (!statusWithSpec.isOK()) { return statusWithSpec; @@ -1289,6 +1292,24 @@ StatusWith<BSONObj> IndexCatalog::_fixIndexSpec(const BSONObj& spec) { } b.append("name", name); + if (auto collationElt = spec["collation"]) { + // This should already have been verified by _isSpecOk(). + invariant(collationElt.type() == BSONType::Object); + + auto collator = CollatorFactoryInterface::get(txn->getServiceContext()) + ->makeFromBSON(collationElt.Obj()); + if (!collator.isOK()) { + return collator.getStatus(); + } + + b.append("collation", CollationSerializer::specToBSON(collator.getValue()->getSpec())); + } else if (collection->getDefaultCollator()) { + // The user did not specify an explicit collation for this index and the collection has a + // default collator. In this case, the index inherits the collection default. + b.append("collation", + CollationSerializer::specToBSON(collection->getDefaultCollator()->getSpec())); + } + { BSONObjIterator i(o); while (i.more()) { @@ -1299,7 +1320,7 @@ StatusWith<BSONObj> IndexCatalog::_fixIndexSpec(const BSONObj& spec) { // skip } else if (s == "dropDups") { // dropDups is silently ignored and removed from the spec as of SERVER-14710. - } else if (s == "v" || s == "unique" || s == "key" || s == "name") { + } else if (s == "v" || s == "unique" || s == "key" || s == "name" || s == "collation") { // covered above } else { b.append(e); diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h index dac775501a2..a982a6e976b 100644 --- a/src/mongo/db/catalog/index_catalog.h +++ b/src/mongo/db/catalog/index_catalog.h @@ -364,7 +364,9 @@ private: // conform to the standard for insertion. This function adds the 'v' field if it didn't // exist, removes the '_id' field if it exists, applies plugin-level transformations if // appropriate, etc. - static StatusWith<BSONObj> _fixIndexSpec(const BSONObj& spec); + static StatusWith<BSONObj> _fixIndexSpec(OperationContext* txn, + Collection* collection, + const BSONObj& spec); Status _isSpecOk(OperationContext* txn, const BSONObj& spec) const; |