summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorMaddie Zechar <mez2113@columbia.edu>2021-09-28 21:41:31 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-28 22:05:50 +0000
commit48409b32dc3e79e33272f9c34fcbc8eff8b6d0a9 (patch)
tree108cc0948c4ded802b213e0795d40d9b5ee23c64 /src/mongo/db
parent24d3bd41ce7c07c32852c334b52e4b3107136723 (diff)
downloadmongo-48409b32dc3e79e33272f9c34fcbc8eff8b6d0a9.tar.gz
SERVER-54597: Allow users to specify non-default collation on TS
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp17
-rw-r--r--src/mongo/db/views/view_catalog.cpp15
-rw-r--r--src/mongo/db/views/view_catalog.h11
-rw-r--r--src/mongo/db/views/view_catalog_test.cpp8
4 files changed, 36 insertions, 15 deletions
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp
index 81d0b66e25a..23099af5e82 100644
--- a/src/mongo/db/commands/run_aggregate.cpp
+++ b/src/mongo/db/commands/run_aggregate.cpp
@@ -312,7 +312,7 @@ StatusWith<StringMap<ExpressionContext::ResolvedNamespace>> resolveInvolvedNames
// If 'ns' refers to a view namespace, then we resolve its definition.
auto resolveViewDefinition = [&](const NamespaceString& ns,
std::shared_ptr<const ViewCatalog> vcp) -> Status {
- auto resolvedView = vcp->resolveView(opCtx, ns);
+ auto resolvedView = vcp->resolveView(opCtx, ns, boost::none);
if (!resolvedView.isOK()) {
return resolvedView.getStatus().withContext(
str::stream() << "Failed to resolve view '" << involvedNs.ns());
@@ -417,7 +417,7 @@ Status collatorCompatibleWithPipeline(OperationContext* opCtx,
}
if (!CollatorInterface::collatorsMatch(view->defaultCollator(), collator)) {
return {ErrorCodes::OptionNotSupportedOnView,
- str::stream() << "Cannot override default collation of view "
+ str::stream() << "Cannot override a view's default collation"
<< potentialViewNs.ns()};
}
}
@@ -681,16 +681,23 @@ Status runAggregate(OperationContext* opCtx,
if (!request.getCollation().get_value_or(BSONObj()).isEmpty()) {
invariant(collatorToUse); // Should already be resolved at this point.
if (!CollatorInterface::collatorsMatch(ctx->getView()->defaultCollator(),
- collatorToUse->get())) {
+ collatorToUse->get()) &&
+ !ctx->getView()->timeseries()) {
+
return {ErrorCodes::OptionNotSupportedOnView,
"Cannot override a view's default collation"};
}
}
-
+ // Queries on timeseries views may specify non-default collation whereas queries
+ // on all other types of views must match the default collator (the collation use
+ // to originally create that collections). Thus in the case of operations on TS
+ // views, we use the request's collation.
+ auto timeSeriesCollator =
+ ctx->getView()->timeseries() ? request.getCollation() : boost::none;
auto resolvedView = uassertStatusOK(DatabaseHolder::get(opCtx)
->getViewCatalog(opCtx, nss.db())
- ->resolveView(opCtx, nss));
+ ->resolveView(opCtx, nss, timeSeriesCollator));
// With the view & collation resolved, we can relinquish locks.
ctx.reset();
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index e84d0c0fa69..84e0f7b46a8 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -714,8 +714,10 @@ std::shared_ptr<const ViewDefinition> ViewCatalog::lookupWithoutValidatingDurabl
return _lookup(opCtx, ns, ViewCatalogLookupBehavior::kAllowInvalidDurableViews);
}
-StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
- const NamespaceString& nss) const {
+StatusWith<ResolvedView> ViewCatalog::resolveView(
+ OperationContext* opCtx,
+ const NamespaceString& nss,
+ boost::optional<BSONObj> timeSeriesCollator) const {
_requireValidCatalog();
// Keep looping until the resolution completes. If the catalog is invalidated during the
@@ -765,8 +767,13 @@ StatusWith<ResolvedView> ViewCatalog::resolveView(OperationContext* opCtx,
resolvedNss = &view->viewOn();
dependencyChain.push_back(*resolvedNss);
if (!collation) {
- collation = view->defaultCollator() ? view->defaultCollator()->getSpec().toBSON()
- : CollationSpec::kSimpleSpec;
+ if (timeSeriesCollator) {
+ collation = *timeSeriesCollator;
+ } else {
+ collation = view->defaultCollator()
+ ? view->defaultCollator()->getSpec().toBSON()
+ : CollationSpec::kSimpleSpec;
+ }
}
// Prepend the underlying view's pipeline to the current working pipeline.
diff --git a/src/mongo/db/views/view_catalog.h b/src/mongo/db/views/view_catalog.h
index 0903fb46cb3..b118c532c4c 100644
--- a/src/mongo/db/views/view_catalog.h
+++ b/src/mongo/db/views/view_catalog.h
@@ -136,8 +136,15 @@ public:
* Resolve the views on 'nss', transforming the pipeline appropriately. This function returns a
* fully-resolved view definition containing the backing namespace, the resolved pipeline and
* the collation to use for the operation.
- */
- StatusWith<ResolvedView> resolveView(OperationContext* opCtx, const NamespaceString& nss) const;
+ *
+ * With SERVER-54597, we allow queries on timeseries collections *only* to specify non-default
+ * collations. So in the case of queries on timeseries collections, we create a ResolvedView
+ * with the request's collation (timeSeriesCollator) rather than the collection's default
+ * collator.
+ */
+ StatusWith<ResolvedView> resolveView(OperationContext* opCtx,
+ const NamespaceString& nss,
+ boost::optional<BSONObj> timeseriesCollator) const;
/**
* Usage statistics about this view catalog.
diff --git a/src/mongo/db/views/view_catalog_test.cpp b/src/mongo/db/views/view_catalog_test.cpp
index 8dedba3d753..f468f5feac9 100644
--- a/src/mongo/db/views/view_catalog_test.cpp
+++ b/src/mongo/db/views/view_catalog_test.cpp
@@ -673,7 +673,7 @@ TEST_F(ViewCatalogFixture, ResolveViewCorrectPipeline) {
ASSERT_OK(createView(operationContext(), view3, view2, pipeline3.arr(), emptyCollation));
Lock::DBLock dbLock(operationContext(), "db", MODE_IX);
- auto resolvedView = getViewCatalog()->resolveView(operationContext(), view3);
+ auto resolvedView = getViewCatalog()->resolveView(operationContext(), view3, boost::none);
ASSERT(resolvedView.isOK());
std::vector<BSONObj> expected = {BSON("$match" << BSON("foo" << 1)),
@@ -693,8 +693,8 @@ TEST_F(ViewCatalogFixture, ResolveViewOnCollectionNamespace) {
const NamespaceString collectionNamespace("db.coll");
Lock::DBLock dbLock(operationContext(), "db", MODE_IS);
- auto resolvedView =
- uassertStatusOK(getViewCatalog()->resolveView(operationContext(), collectionNamespace));
+ auto resolvedView = uassertStatusOK(
+ getViewCatalog()->resolveView(operationContext(), collectionNamespace, boost::none));
ASSERT_EQ(resolvedView.getNamespace(), collectionNamespace);
ASSERT_EQ(resolvedView.getPipeline().size(), 0U);
@@ -717,7 +717,7 @@ TEST_F(ViewCatalogFixture, ResolveViewCorrectlyExtractsDefaultCollation) {
ASSERT_OK(createView(operationContext(), view2, view1, pipeline2.arr(), collation));
Lock::DBLock dbLock(operationContext(), "db", MODE_IS);
- auto resolvedView = getViewCatalog()->resolveView(operationContext(), view2);
+ auto resolvedView = getViewCatalog()->resolveView(operationContext(), view2, boost::none);
ASSERT(resolvedView.isOK());
ASSERT_EQ(resolvedView.getValue().getNamespace(), viewOn);