summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/catalog/collection.h14
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp51
-rw-r--r--src/mongo/db/catalog/collection_impl.h4
-rw-r--r--src/mongo/db/catalog/collection_mock.h6
-rw-r--r--src/mongo/db/commands/create_indexes.cpp55
5 files changed, 72 insertions, 58 deletions
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index 29c23c55c41..41ce7a9fc74 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -1,4 +1,3 @@
-
/**
* Copyright (C) 2018-present MongoDB, Inc.
*
@@ -33,6 +32,7 @@
#include <cstdint>
#include <memory>
#include <string>
+#include <vector>
#include "mongo/base/status.h"
#include "mongo/base/status_with.h"
@@ -431,6 +431,18 @@ public:
virtual const CollatorInterface* getDefaultCollator() const = 0;
/**
+ * Fills in each index specification with collation information from this collection and returns
+ * the new index specifications.
+ *
+ * The returned index specifications will not be equivalent to the ones specified in
+ * 'indexSpecs' if any missing collation information were filled in; however, the returned index
+ * specifications will match the form stored in the IndexCatalog should any of these indexes
+ * already exist.
+ */
+ virtual StatusWith<std::vector<BSONObj>> addCollationDefaultsToIndexSpecsForCreate(
+ OperationContext* opCtx, const std::vector<BSONObj>& indexSpecs) const = 0;
+
+ /**
* Returns a plan executor for a collection scan over this collection.
*/
virtual std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> makePlanExecutor(
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 79503488959..a1e0153720e 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1,4 +1,3 @@
-
/**
* Copyright (C) 2018-present MongoDB, Inc.
*
@@ -50,6 +49,7 @@
#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_catalog_impl.h"
#include "mongo/db/catalog/index_consistency.h"
+#include "mongo/db/catalog/index_key_validate.h"
#include "mongo/db/catalog/namespace_uuid_cache.h"
#include "mongo/db/catalog/uuid_catalog.h"
#include "mongo/db/clientcursor.h"
@@ -57,12 +57,14 @@
#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/curop.h"
#include "mongo/db/index/index_access_method.h"
+#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/keypattern.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/ops/update_request.h"
#include "mongo/db/query/collation/collator_factory_interface.h"
+#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/internal_plans.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/replication_coordinator.h"
@@ -959,6 +961,53 @@ const CollatorInterface* CollectionImpl::getDefaultCollator() const {
return _collator.get();
}
+StatusWith<std::vector<BSONObj>> CollectionImpl::addCollationDefaultsToIndexSpecsForCreate(
+ OperationContext* opCtx, const std::vector<BSONObj>& originalIndexSpecs) const {
+ std::vector<BSONObj> newIndexSpecs;
+
+ auto collator = getDefaultCollator(); // could be null.
+ auto collatorFactory = CollatorFactoryInterface::get(opCtx->getServiceContext());
+
+ for (const auto& originalIndexSpec : originalIndexSpecs) {
+ auto validateResult =
+ index_key_validate::validateIndexSpecCollation(opCtx, originalIndexSpec, collator);
+ if (!validateResult.isOK()) {
+ return validateResult.getStatus().withContext(
+ str::stream()
+ << "failed to add collation information to index spec for index creation: "
+ << originalIndexSpec);
+ }
+ const auto& newIndexSpec = validateResult.getValue();
+
+ auto keyPattern = newIndexSpec[IndexDescriptor::kKeyPatternFieldName].Obj();
+ if (IndexDescriptor::isIdIndexPattern(keyPattern)) {
+ std::unique_ptr<CollatorInterface> indexCollator;
+ if (auto collationElem = newIndexSpec[IndexDescriptor::kCollationFieldName]) {
+ auto indexCollatorResult = collatorFactory->makeFromBSON(collationElem.Obj());
+ // validateIndexSpecCollation() should have checked that the index collation spec is
+ // valid.
+ invariant(indexCollatorResult.getStatus(),
+ str::stream() << "invalid collation in index spec: " << newIndexSpec);
+ indexCollator = std::move(indexCollatorResult.getValue());
+ }
+ if (!CollatorInterface::collatorsMatch(collator, indexCollator.get())) {
+ return {ErrorCodes::BadValue,
+ str::stream() << "The _id index must have the same collation as the "
+ "collection. Index collation: "
+ << (indexCollator.get() ? indexCollator->getSpec().toBSON()
+ : CollationSpec::kSimpleSpec)
+ << ", collection collation: "
+ << (collator ? collator->getSpec().toBSON()
+ : CollationSpec::kSimpleSpec)};
+ }
+ }
+
+ newIndexSpecs.push_back(newIndexSpec);
+ }
+
+ return newIndexSpecs;
+}
+
namespace {
using ValidateResultsMap = std::map<std::string, ValidateResults>;
diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h
index 19ec048b572..149c77d75f6 100644
--- a/src/mongo/db/catalog/collection_impl.h
+++ b/src/mongo/db/catalog/collection_impl.h
@@ -1,4 +1,3 @@
-
/**
* Copyright (C) 2018-present MongoDB, Inc.
*
@@ -353,6 +352,9 @@ public:
*/
const CollatorInterface* getDefaultCollator() const final;
+ StatusWith<std::vector<BSONObj>> addCollationDefaultsToIndexSpecsForCreate(
+ OperationContext* opCtx, const std::vector<BSONObj>& indexSpecs) const final;
+
std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> makePlanExecutor(
OperationContext* opCtx,
PlanExecutor::YieldPolicy yieldPolicy,
diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h
index 4b82f16f378..30e2ee1fee6 100644
--- a/src/mongo/db/catalog/collection_mock.h
+++ b/src/mongo/db/catalog/collection_mock.h
@@ -1,4 +1,3 @@
-
/**
* Copyright (C) 2018-present MongoDB, Inc.
*
@@ -267,6 +266,11 @@ public:
std::abort();
}
+ StatusWith<std::vector<BSONObj>> addCollationDefaultsToIndexSpecsForCreate(
+ OperationContext* opCtx, const std::vector<BSONObj>& indexSpecs) const {
+ std::abort();
+ }
+
std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> makePlanExecutor(
OperationContext* opCtx,
PlanExecutor::YieldPolicy yieldPolicy,
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index f613c0d6b1f..ae73af62bb7 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -52,7 +52,6 @@
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/op_observer.h"
#include "mongo/db/ops/insert.h"
-#include "mongo/db/query/collation/collator_factory_interface.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/s/collection_metadata.h"
@@ -164,57 +163,6 @@ StatusWith<std::vector<BSONObj>> parseAndValidateIndexSpecs(
}
/**
- * Returns index specifications with attributes (such as "collation") that are inherited from the
- * collection filled in.
- *
- * The returned index specifications will not be equivalent to the ones specified as 'indexSpecs' if
- * any missing attributes were filled in; however, the returned index specifications will match the
- * form stored in the IndexCatalog should any of these indexes already exist.
- */
-StatusWith<std::vector<BSONObj>> resolveCollectionDefaultProperties(
- OperationContext* opCtx, const Collection* collection, std::vector<BSONObj> indexSpecs) {
- std::vector<BSONObj> indexSpecsWithDefaults = std::move(indexSpecs);
-
- for (size_t i = 0, numIndexSpecs = indexSpecsWithDefaults.size(); i < numIndexSpecs; ++i) {
- auto indexSpecStatus = index_key_validate::validateIndexSpecCollation(
- opCtx, indexSpecsWithDefaults[i], collection->getDefaultCollator());
- if (!indexSpecStatus.isOK()) {
- return indexSpecStatus.getStatus();
- }
- auto indexSpec = indexSpecStatus.getValue();
-
- if (IndexDescriptor::isIdIndexPattern(
- indexSpec[IndexDescriptor::kKeyPatternFieldName].Obj())) {
- std::unique_ptr<CollatorInterface> indexCollator;
- if (auto collationElem = indexSpec[IndexDescriptor::kCollationFieldName]) {
- auto collatorStatus = CollatorFactoryInterface::get(opCtx->getServiceContext())
- ->makeFromBSON(collationElem.Obj());
- // validateIndexSpecCollation() should have checked that the index collation spec is
- // valid.
- invariant(collatorStatus.getStatus());
- indexCollator = std::move(collatorStatus.getValue());
- }
- if (!CollatorInterface::collatorsMatch(collection->getDefaultCollator(),
- indexCollator.get())) {
- return {ErrorCodes::BadValue,
- str::stream() << "The _id index must have the same collation as the "
- "collection. Index collation: "
- << (indexCollator.get() ? indexCollator->getSpec().toBSON()
- : CollationSpec::kSimpleSpec)
- << ", collection collation: "
- << (collection->getDefaultCollator()
- ? collection->getDefaultCollator()->getSpec().toBSON()
- : CollationSpec::kSimpleSpec)};
- }
- }
-
- indexSpecsWithDefaults[i] = indexSpec;
- }
-
- return indexSpecsWithDefaults;
-}
-
-/**
* Returns a vector of index specs with the filled in collection default options and removes any
* indexes that already exist on the collection. If the returned vector is empty after returning, no
* new indexes need to be built. Throws on error.
@@ -222,8 +170,7 @@ StatusWith<std::vector<BSONObj>> resolveCollectionDefaultProperties(
std::vector<BSONObj> resolveDefaultsAndRemoveExistingIndexes(OperationContext* opCtx,
const Collection* collection,
std::vector<BSONObj> validatedSpecs) {
- auto swDefaults =
- resolveCollectionDefaultProperties(opCtx, collection, std::move(validatedSpecs));
+ auto swDefaults = collection->addCollationDefaultsToIndexSpecsForCreate(opCtx, validatedSpecs);
uassertStatusOK(swDefaults.getStatus());
auto indexCatalog = collection->getIndexCatalog();