diff options
author | David Percy <david.percy@mongodb.com> | 2023-01-23 18:32:43 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-02-04 00:28:43 +0000 |
commit | 2110371e64514ce3ddae01c08f5b225ba5eaadc5 (patch) | |
tree | 5ac4722497ae476869eb4b20fe9f51f38796f3e9 /src/mongo | |
parent | 6b7b85d787f099d1c0ce0a4199a1c3cc61c21647 (diff) | |
download | mongo-2110371e64514ce3ddae01c08f5b225ba5eaadc5.tar.gz |
SERVER-73110 Each shard should check extended-range for timeseries sorting
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/catalog/virtual_collection_impl.h | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/run_aggregate.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_context.h | 11 | ||||
-rw-r--r-- | src/mongo/db/query/multiple_collection_accessor.h | 11 | ||||
-rw-r--r-- | src/mongo/db/sorter/sorter.cpp | 3 |
6 files changed, 46 insertions, 2 deletions
diff --git a/src/mongo/db/catalog/virtual_collection_impl.h b/src/mongo/db/catalog/virtual_collection_impl.h index 055c61283a2..4366d86ccd5 100644 --- a/src/mongo/db/catalog/virtual_collection_impl.h +++ b/src/mongo/db/catalog/virtual_collection_impl.h @@ -242,7 +242,8 @@ public: } bool getRequiresTimeseriesExtendedRangeSupport() const final { - unimplementedTasserted(); + // A virtual collection is never a time-series collection, so it never requires + // extended-range support. return false; } diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp index 8db9c787f7f..8868ce91a8b 100644 --- a/src/mongo/db/commands/run_aggregate.cpp +++ b/src/mongo/db/commands/run_aggregate.cpp @@ -974,6 +974,13 @@ Status runAggregate(OperationContext* opCtx, ? collections.getMainCollection()->getCollectionOptions() : boost::optional<CollectionOptions>(boost::none)); + // If any involved collection contains extended-range data, set a flag which individual + // DocumentSource parsers can check. + collections.forEach([&](const CollectionPtr& coll) { + if (coll->getRequiresTimeseriesExtendedRangeSupport()) + expCtx->setRequiresTimeseriesExtendedRangeSupport(true); + }); + expCtx->startExpressionCounters(); auto pipeline = Pipeline::parse(request.getPipeline(), expCtx); curOp->beginQueryPlanningTimer(); diff --git a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp index bc4d86b2744..256804b978f 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp @@ -291,6 +291,11 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceInternalUnpackBucket::createF // If neither "include" nor "exclude" is specified, the default is "exclude": [] and // if that's the case, no field will be added to 'bucketSpec.fieldSet' in the for-loop below. BucketSpec bucketSpec; + // Use extended-range support if any individual collection requires it, even if 'specElem' + // doesn't mention this flag. + if (expCtx->getRequiresTimeseriesExtendedRangeSupport()) { + bucketSpec.setUsesExtendedRange(true); + } auto hasIncludeExclude = false; auto hasTimeField = false; auto hasBucketMaxSpanSeconds = false; @@ -504,6 +509,14 @@ void DocumentSourceInternalUnpackBucket::serializeToArray( if (_assumeNoMixedSchemaData) out.addField(kAssumeNoMixedSchemaData, Value(_assumeNoMixedSchemaData)); + if (spec.usesExtendedRange()) { + // Include this flag so that 'explain' is more helpful. + // But this is not so useful for communicating from one process to another, + // because mongos and/or the primary shard don't know whether any other shard + // has extended-range data. + out.addField(kUsesExtendedRange, Value{true}); + } + if (!spec.computedMetaProjFields().empty()) out.addField("computedMetaProjFields", Value{[&] { std::vector<Value> compFields; diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index 3ec3554a336..a0f04003479 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -511,6 +511,15 @@ public: _gotTemporarilyUnavailableException = v; } + // Sets or clears a flag which tells DocumentSource parsers whether any involved Collection + // may contain extended-range dates. + void setRequiresTimeseriesExtendedRangeSupport(bool v) { + _requiresTimeseriesExtendedRangeSupport = v; + } + bool getRequiresTimeseriesExtendedRangeSupport() const { + return _requiresTimeseriesExtendedRangeSupport; + } + protected: static const int kInterruptCheckPeriod = 128; @@ -535,6 +544,8 @@ protected: bool _isCappedDelete = false; + bool _requiresTimeseriesExtendedRangeSupport = false; + private: boost::optional<ExpressionCounters> _expressionCounters = boost::none; bool _gotTemporarilyUnavailableException = false; diff --git a/src/mongo/db/query/multiple_collection_accessor.h b/src/mongo/db/query/multiple_collection_accessor.h index bf8c0ad5fe9..04c766770bb 100644 --- a/src/mongo/db/query/multiple_collection_accessor.h +++ b/src/mongo/db/query/multiple_collection_accessor.h @@ -101,6 +101,17 @@ public: _secondaryColls.clear(); } + void forEach(std::function<void(const CollectionPtr&)> func) const { + if (hasMainCollection()) { + func(getMainCollection()); + } + for (const auto& [name, coll] : getSecondaryCollections()) { + if (coll) { + func(coll); + } + } + } + private: const CollectionPtr* _mainColl{&CollectionPtr::null}; diff --git a/src/mongo/db/sorter/sorter.cpp b/src/mongo/db/sorter/sorter.cpp index 411c85ffbdb..92680a15971 100644 --- a/src/mongo/db/sorter/sorter.cpp +++ b/src/mongo/db/sorter/sorter.cpp @@ -1468,7 +1468,8 @@ void BoundedSorter<Key, Value, Comparator, BoundMaker>::add(Key key, Value value invariant(!_done); // If a new value violates what we thought was our min bound, something has gone wrong. uassert(6369910, - "BoundedSorter input is too out-of-order.", + str::stream() << "BoundedSorter input is too out-of-order: with bound " + << _min->toString() << ", did not expect input " << key.toString(), !_checkInput || !_min || compare(*_min, key) <= 0); // Each new item can potentially give us a tighter bound (a higher min). |