diff options
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/exec/bucket_unpacker.cpp | 228 | ||||
-rw-r--r-- | src/mongo/db/exec/bucket_unpacker.h | 12 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_internal_unpack_bucket.h | 5 | ||||
-rw-r--r-- | src/mongo/db/views/resolved_view.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/views/resolved_view.h | 9 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog_helpers.cpp | 5 |
7 files changed, 197 insertions, 94 deletions
diff --git a/src/mongo/db/exec/bucket_unpacker.cpp b/src/mongo/db/exec/bucket_unpacker.cpp index 37847fc80c4..fd3e790ba5a 100644 --- a/src/mongo/db/exec/bucket_unpacker.cpp +++ b/src/mongo/db/exec/bucket_unpacker.cpp @@ -282,8 +282,9 @@ std::unique_ptr<MatchExpression> createComparisonPredicate( // For $eq, make both a $lte against 'control.min' and a $gte predicate against // 'control.max'. // - // If the comparison is against the 'time' field, include a predicate against the _id - // field which is converted to the maximum for the corresponding range of ObjectIds and + // If the comparison is against the 'time' field and we haven't stored a time outside of + // the 32 bit range, include a predicate against the _id field which is converted to + // the maximum for the corresponding range of ObjectIds and // is adjusted by the max range for a bucket to approximate the max bucket value given // the min. Also include a predicate against the _id field which is converted to the // minimum for the range of ObjectIds corresponding to the given date. In @@ -293,60 +294,79 @@ std::unique_ptr<MatchExpression> createComparisonPredicate( // // The same procedure applies to aggregation expressions of the form // {$expr: {$eq: [...]}} that can be rewritten to use $_internalExprEq. - return isTimeField - ? makePredicate( - MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), - MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, - minTime.firstElement()), - MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), - MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, - maxTime.firstElement()), - MatchExprPredicate<LTEMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<LTEMatchExpression>(matchExprData, - bucketMaxSpanSeconds)), - MatchExprPredicate<GTEMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<GTEMatchExpression>(matchExprData, - bucketMaxSpanSeconds))) - : makeOr(makeVector<std::unique_ptr<MatchExpression>>( - makePredicate(MatchExprPredicate<InternalExprLTEMatchExpression>( - minPath, matchExprData), - MatchExprPredicate<InternalExprGTEMatchExpression>( - maxPath, matchExprData)), - createTypeEqualityPredicate( - pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + if (!isTimeField) { + return makeOr(makeVector<std::unique_ptr<MatchExpression>>( + makePredicate( + MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData)), + createTypeEqualityPredicate(pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + } else if (bucketSpec.usesExtendedRange()) { + return makePredicate( + MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, + minTime.firstElement()), + MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, + maxTime.firstElement())); + } else { + return makePredicate( + MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, + minTime.firstElement()), + MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, + maxTime.firstElement()), + MatchExprPredicate<LTEMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<LTEMatchExpression>(matchExprData, + bucketMaxSpanSeconds)), + MatchExprPredicate<GTEMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<GTEMatchExpression>(matchExprData, + bucketMaxSpanSeconds))); + } + MONGO_UNREACHABLE_TASSERT(6646903); case MatchExpression::GT: case MatchExpression::INTERNAL_EXPR_GT: // For $gt, make a $gt predicate against 'control.max'. In addition, if the comparison - // is against the 'time' field, include a predicate against the _id field which is - // converted to the maximum for the corresponding range of ObjectIds and is adjusted - // by the max range for a bucket to approximate the max bucket value given the min. In - // addition, we include a {'control.min' : {$gt: 'time - bucketMaxSpanSeconds'}} + // is against the 'time' field, and the collection doesn't contain times outside the + // 32 bit range, include a predicate against the _id field which is converted to the + // maximum for the corresponding range of ObjectIds and is adjusted by the max range + // for a bucket to approximate the max bucket value given the min. + // + // In addition, we include a {'control.min' : {$gt: 'time - bucketMaxSpanSeconds'}} // predicate which will be helpful in reducing bounds for index scans on 'time' field // and routing on mongos. // // The same procedure applies to aggregation expressions of the form // {$expr: {$gt: [...]}} that can be rewritten to use $_internalExprGt. - return isTimeField - ? makePredicate( - MatchExprPredicate<InternalExprGTMatchExpression>(maxPath, matchExprData), - MatchExprPredicate<InternalExprGTMatchExpression>(minPath, - minTime.firstElement()), - MatchExprPredicate<GTMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<GTMatchExpression>(matchExprData, - bucketMaxSpanSeconds))) - : makeOr(makeVector<std::unique_ptr<MatchExpression>>( - std::make_unique<InternalExprGTMatchExpression>(maxPath, matchExprData), - createTypeEqualityPredicate( - pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + if (!isTimeField) { + return makeOr(makeVector<std::unique_ptr<MatchExpression>>( + std::make_unique<InternalExprGTMatchExpression>(maxPath, matchExprData), + createTypeEqualityPredicate(pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + } else if (bucketSpec.usesExtendedRange()) { + return makePredicate( + MatchExprPredicate<InternalExprGTMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprGTMatchExpression>(minPath, + minTime.firstElement())); + } else { + return makePredicate( + MatchExprPredicate<InternalExprGTMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprGTMatchExpression>(minPath, + minTime.firstElement()), + MatchExprPredicate<GTMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<GTMatchExpression>(matchExprData, + bucketMaxSpanSeconds))); + } + MONGO_UNREACHABLE_TASSERT(6646904); case MatchExpression::GTE: case MatchExpression::INTERNAL_EXPR_GTE: // For $gte, make a $gte predicate against 'control.max'. In addition, if the comparison - // is against the 'time' field, include a predicate against the _id field which is + // is against the 'time' field, and the collection doesn't contain times outside the + // 32 bit range, include a predicate against the _id field which is // converted to the minimum for the corresponding range of ObjectIds and is adjusted // by the max range for a bucket to approximate the max bucket value given the min. In // addition, we include a {'control.min' : {$gte: 'time - bucketMaxSpanSeconds'}} @@ -355,49 +375,67 @@ std::unique_ptr<MatchExpression> createComparisonPredicate( // // The same procedure applies to aggregation expressions of the form // {$expr: {$gte: [...]}} that can be rewritten to use $_internalExprGte. - return isTimeField - ? makePredicate( - MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), - MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, - minTime.firstElement()), - MatchExprPredicate<GTEMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<GTEMatchExpression>(matchExprData, - bucketMaxSpanSeconds))) - : makeOr(makeVector<std::unique_ptr<MatchExpression>>( - std::make_unique<InternalExprGTEMatchExpression>(maxPath, matchExprData), - createTypeEqualityPredicate( - pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + if (!isTimeField) { + return makeOr(makeVector<std::unique_ptr<MatchExpression>>( + std::make_unique<InternalExprGTEMatchExpression>(maxPath, matchExprData), + createTypeEqualityPredicate(pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + } else if (bucketSpec.usesExtendedRange()) { + return makePredicate( + MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, + minTime.firstElement())); + } else { + return makePredicate( + MatchExprPredicate<InternalExprGTEMatchExpression>(maxPath, matchExprData), + MatchExprPredicate<InternalExprGTEMatchExpression>(minPath, + minTime.firstElement()), + MatchExprPredicate<GTEMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<GTEMatchExpression>(matchExprData, + bucketMaxSpanSeconds))); + } + MONGO_UNREACHABLE_TASSERT(6646905); case MatchExpression::LT: case MatchExpression::INTERNAL_EXPR_LT: // For $lt, make a $lt predicate against 'control.min'. In addition, if the comparison // is against the 'time' field, include a predicate against the _id field which is - // converted to the minimum for the corresponding range of ObjectIds. In - // addition, we include a {'control.max' : {$lt: 'time + bucketMaxSpanSeconds'}} + // converted to the minimum for the corresponding range of ObjectIds, unless the + // collection contain extended range dates which won't fit int the 32 bits allocated + // for _id. + // + // In addition, we include a {'control.max' : {$lt: 'time + bucketMaxSpanSeconds'}} // predicate which will be helpful in reducing bounds for index scans on 'time' field // and routing on mongos. // // The same procedure applies to aggregation expressions of the form // {$expr: {$lt: [...]}} that can be rewritten to use $_internalExprLt. - return isTimeField - ? makePredicate( - MatchExprPredicate<InternalExprLTMatchExpression>(minPath, matchExprData), - MatchExprPredicate<InternalExprLTMatchExpression>(maxPath, - maxTime.firstElement()), - MatchExprPredicate<LTMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<LTMatchExpression>(matchExprData, - bucketMaxSpanSeconds))) - : makeOr(makeVector<std::unique_ptr<MatchExpression>>( - std::make_unique<InternalExprLTMatchExpression>(minPath, matchExprData), - createTypeEqualityPredicate( - pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + if (!isTimeField) { + return makeOr(makeVector<std::unique_ptr<MatchExpression>>( + std::make_unique<InternalExprLTMatchExpression>(minPath, matchExprData), + createTypeEqualityPredicate(pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + } else if (bucketSpec.usesExtendedRange()) { + return makePredicate( + MatchExprPredicate<InternalExprLTMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprLTMatchExpression>(maxPath, + maxTime.firstElement())); + } else { + return makePredicate( + MatchExprPredicate<InternalExprLTMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprLTMatchExpression>(maxPath, + maxTime.firstElement()), + MatchExprPredicate<LTMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<LTMatchExpression>(matchExprData, + bucketMaxSpanSeconds))); + } + MONGO_UNREACHABLE_TASSERT(6646906); case MatchExpression::LTE: case MatchExpression::INTERNAL_EXPR_LTE: // For $lte, make a $lte predicate against 'control.min'. In addition, if the comparison - // is against the 'time' field, include a predicate against the _id field which is + // is against the 'time' field, and the collection doesn't contain times outside the + // 32 bit range, include a predicate against the _id field which is // converted to the maximum for the corresponding range of ObjectIds. In // addition, we include a {'control.max' : {$lte: 'time + bucketMaxSpanSeconds'}} // predicate which will be helpful in reducing bounds for index scans on 'time' field @@ -405,19 +443,26 @@ std::unique_ptr<MatchExpression> createComparisonPredicate( // // The same procedure applies to aggregation expressions of the form // {$expr: {$lte: [...]}} that can be rewritten to use $_internalExprLte. - return isTimeField - ? makePredicate( - MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), - MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, - maxTime.firstElement()), - MatchExprPredicate<LTEMatchExpression, Value>( - kBucketIdFieldName, - constructObjectIdValue<LTEMatchExpression>(matchExprData, - bucketMaxSpanSeconds))) - : makeOr(makeVector<std::unique_ptr<MatchExpression>>( - std::make_unique<InternalExprLTEMatchExpression>(minPath, matchExprData), - createTypeEqualityPredicate( - pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + if (!isTimeField) { + return makeOr(makeVector<std::unique_ptr<MatchExpression>>( + std::make_unique<InternalExprLTEMatchExpression>(minPath, matchExprData), + createTypeEqualityPredicate(pExpCtx, matchExprPath, assumeNoMixedSchemaData))); + } else if (bucketSpec.usesExtendedRange()) { + return makePredicate( + MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, + maxTime.firstElement())); + } else { + return makePredicate( + MatchExprPredicate<InternalExprLTEMatchExpression>(minPath, matchExprData), + MatchExprPredicate<InternalExprLTEMatchExpression>(maxPath, + maxTime.firstElement()), + MatchExprPredicate<LTEMatchExpression, Value>( + kBucketIdFieldName, + constructObjectIdValue<LTEMatchExpression>(matchExprData, + bucketMaxSpanSeconds))); + } + MONGO_UNREACHABLE_TASSERT(6646907); default: MONGO_UNREACHABLE_TASSERT(5348302); @@ -1009,12 +1054,14 @@ std::size_t BucketUnpackerV2::numberOfFields() { BucketSpec::BucketSpec(const std::string& timeField, const boost::optional<std::string>& metaField, const std::set<std::string>& fields, - const std::set<std::string>& computedProjections) + const std::set<std::string>& computedProjections, + bool usesExtendedRange) : _fieldSet(fields), _computedMetaProjFields(computedProjections), _timeField(timeField), _timeFieldHashed(FieldNameHasher().hashedFieldName(_timeField)), - _metaField(metaField) { + _metaField(metaField), + _usesExtendedRange(usesExtendedRange) { if (_metaField) { _metaFieldHashed = FieldNameHasher().hashedFieldName(*_metaField); } @@ -1025,7 +1072,8 @@ BucketSpec::BucketSpec(const BucketSpec& other) _computedMetaProjFields(other._computedMetaProjFields), _timeField(other._timeField), _timeFieldHashed(HashedFieldName{_timeField, other._timeFieldHashed->hash()}), - _metaField(other._metaField) { + _metaField(other._metaField), + _usesExtendedRange(other._usesExtendedRange) { if (_metaField) { _metaFieldHashed = HashedFieldName{*_metaField, other._metaFieldHashed->hash()}; } @@ -1036,7 +1084,8 @@ BucketSpec::BucketSpec(BucketSpec&& other) _computedMetaProjFields(std::move(other._computedMetaProjFields)), _timeField(std::move(other._timeField)), _timeFieldHashed(HashedFieldName{_timeField, other._timeFieldHashed->hash()}), - _metaField(std::move(other._metaField)) { + _metaField(std::move(other._metaField)), + _usesExtendedRange(other._usesExtendedRange) { if (_metaField) { _metaFieldHashed = HashedFieldName{*_metaField, other._metaFieldHashed->hash()}; } @@ -1052,6 +1101,7 @@ BucketSpec& BucketSpec::operator=(const BucketSpec& other) { if (_metaField) { _metaFieldHashed = HashedFieldName{*_metaField, other._metaFieldHashed->hash()}; } + _usesExtendedRange = other._usesExtendedRange; } return *this; } diff --git a/src/mongo/db/exec/bucket_unpacker.h b/src/mongo/db/exec/bucket_unpacker.h index 7e32629407d..8f7f8210618 100644 --- a/src/mongo/db/exec/bucket_unpacker.h +++ b/src/mongo/db/exec/bucket_unpacker.h @@ -58,7 +58,8 @@ public: BucketSpec(const std::string& timeField, const boost::optional<std::string>& metaField, const std::set<std::string>& fields = {}, - const std::set<std::string>& computedProjections = {}); + const std::set<std::string>& computedProjections = {}, + bool usesExtendedRange = false); BucketSpec(const BucketSpec&); BucketSpec(BucketSpec&&); @@ -104,6 +105,14 @@ public: _computedMetaProjFields.erase(field); } + void setUsesExtendedRange(bool usesExtendedRange) { + _usesExtendedRange = usesExtendedRange; + } + + bool usesExtendedRange() const { + return _usesExtendedRange; + } + // Returns whether 'field' depends on a pushed down $addFields or computed $project. bool fieldIsComputed(StringData field) const; @@ -197,6 +206,7 @@ private: boost::optional<std::string> _metaField = boost::none; boost::optional<HashedFieldName> _metaFieldHashed = boost::none; + bool _usesExtendedRange = false; }; /** 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 a950aeee4f4..9ef6d892a51 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp @@ -246,6 +246,7 @@ DocumentSourceInternalUnpackBucket::DocumentSourceInternalUnpackBucket( bool assumeNoMixedSchemaData) : DocumentSource(kStageNameInternal, expCtx), _assumeNoMixedSchemaData(assumeNoMixedSchemaData), + _bucketUnpacker(std::move(bucketUnpacker)), _bucketMaxSpanSeconds{bucketMaxSpanSeconds} {} @@ -353,6 +354,12 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceInternalUnpackBucket::createF << " field must be a bool, got: " << elem.type(), elem.type() == BSONType::Bool); bucketSpec.includeMaxTimeAsMetadata = elem.boolean(); + } else if (fieldName == kUsesExtendedRange) { + uassert(6646901, + str::stream() << kUsesExtendedRange + << " field must be a bool, got: " << elem.type(), + elem.type() == BSONType::Bool); + bucketSpec.setUsesExtendedRange(elem.boolean()); } else { uasserted(5346506, str::stream() diff --git a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.h b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.h index 76cb9c7ca5f..4dd93046533 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.h +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.h @@ -47,6 +47,7 @@ public: static constexpr StringData kInclude = "include"_sd; static constexpr StringData kExclude = "exclude"_sd; static constexpr StringData kAssumeNoMixedSchemaData = "assumeNoMixedSchemaData"_sd; + static constexpr StringData kUsesExtendedRange = "usesExtendedRange"_sd; static constexpr StringData kBucketMaxSpanSeconds = "bucketMaxSpanSeconds"_sd; static constexpr StringData kIncludeMinTimeAsMetadata = "includeMinTimeAsMetadata"_sd; static constexpr StringData kIncludeMaxTimeAsMetadata = "includeMaxTimeAsMetadata"_sd; @@ -250,6 +251,10 @@ private: // predicates in order to ensure correctness. bool _assumeNoMixedSchemaData = false; + // If any bucket contains dates outside the range of 1970-2038, we are unable to rely on + // the _id index, as _id is truncates to 32 bits + bool _usesExtendedRange = false; + BucketUnpacker _bucketUnpacker; int _bucketMaxSpanSeconds; diff --git a/src/mongo/db/views/resolved_view.cpp b/src/mongo/db/views/resolved_view.cpp index 77577aba02d..4c864be4696 100644 --- a/src/mongo/db/views/resolved_view.cpp +++ b/src/mongo/db/views/resolved_view.cpp @@ -91,11 +91,22 @@ ResolvedView ResolvedView::fromBSON(const BSONObj& commandResponseObj) { mixedSchema = boost::optional<bool>(mixedSchemaElem.boolean()); } + boost::optional<bool> usesExtendedRange = boost::none; + if (auto usesExtendedRangeElem = viewDef[kTimeseriesUsesExtendedRange]) { + uassert(6646910, + str::stream() << "view definition must have " << kTimeseriesUsesExtendedRange + << " of type bool or no such field", + usesExtendedRangeElem.type() == BSONType::Bool); + + usesExtendedRange = boost::optional<bool>(usesExtendedRangeElem.boolean()); + } + return {NamespaceString(viewDef["ns"].valueStringData()), std::move(pipeline), std::move(collationSpec), std::move(timeseriesOptions), - std::move(mixedSchema)}; + std::move(mixedSchema), + std::move(usesExtendedRange)}; } void ResolvedView::serialize(BSONObjBuilder* builder) const { @@ -109,6 +120,10 @@ void ResolvedView::serialize(BSONObjBuilder* builder) const { // Only serialize if it doesn't contain mixed data. if ((_timeseriesMayContainMixedData && !(*_timeseriesMayContainMixedData))) subObj.append(kTimeseriesMayContainMixedData, *_timeseriesMayContainMixedData); + + if ((_timeseriesUsesExtendedRange && (*_timeseriesUsesExtendedRange))) + subObj.append(kTimeseriesUsesExtendedRange, *_timeseriesUsesExtendedRange); + if (!_defaultCollation.isEmpty()) { subObj.append("collation", _defaultCollation); } @@ -151,6 +166,7 @@ AggregateCommandRequest ResolvedView::asExpandedViewAggregation( builder.append(elem); } } + resolvedPipeline[1] = BSON(DocumentSourceInternalConvertBucketIndexStats::kStageName << builder.obj()); } else if (resolvedPipeline.size() >= 1 && @@ -164,6 +180,10 @@ AggregateCommandRequest ResolvedView::asExpandedViewAggregation( } builder.append(DocumentSourceInternalUnpackBucket::kAssumeNoMixedSchemaData, ((_timeseriesMayContainMixedData && !(*_timeseriesMayContainMixedData)))); + + builder.append(DocumentSourceInternalUnpackBucket::kUsesExtendedRange, + ((_timeseriesUsesExtendedRange && *_timeseriesUsesExtendedRange))); + resolvedPipeline[0] = BSON(DocumentSourceInternalUnpackBucket::kStageNameInternal << builder.obj()); } @@ -190,6 +210,9 @@ AggregateCommandRequest ResolvedView::asExpandedViewAggregation( } } expandedRequest.setHint(rewritten); + + // JLR Possibly need to handle inappropriately forcing clustered here. Will likely be + // handled by removing the _id predicate, however. } else { expandedRequest.setHint(request.getHint()); } diff --git a/src/mongo/db/views/resolved_view.h b/src/mongo/db/views/resolved_view.h index c0b3ae3d503..82238556288 100644 --- a/src/mongo/db/views/resolved_view.h +++ b/src/mongo/db/views/resolved_view.h @@ -48,12 +48,14 @@ public: std::vector<BSONObj> pipeline, BSONObj defaultCollation, boost::optional<TimeseriesOptions> timeseriesOptions = boost::none, - boost::optional<bool> timeseriesMayContainMixedData = boost::none) + boost::optional<bool> timeseriesMayContainMixedData = boost::none, + boost::optional<bool> timeseriesUsesExtendedRange = boost::none) : _namespace(collectionNs), _pipeline(std::move(pipeline)), _defaultCollation(std::move(defaultCollation)), _timeseriesOptions(timeseriesOptions), - _timeseriesMayContainMixedData(timeseriesMayContainMixedData) {} + _timeseriesMayContainMixedData(timeseriesMayContainMixedData), + _timeseriesUsesExtendedRange(timeseriesUsesExtendedRange) {} static ResolvedView fromBSON(const BSONObj& commandResponseObj); @@ -80,6 +82,8 @@ public: static constexpr auto code = ErrorCodes::CommandOnShardedViewNotSupportedOnMongod; static constexpr StringData kTimeseriesMayContainMixedData = "timeseriesMayContainMixedData"_sd; static constexpr StringData kTimeseriesOptions = "timeseriesOptions"_sd; + static constexpr StringData kTimeseriesUsesExtendedRange = "timeseriesUsesExtendedRange"_sd; + void serialize(BSONObjBuilder* bob) const final; static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj&); @@ -97,6 +101,7 @@ private: boost::optional<TimeseriesOptions> _timeseriesOptions; boost::optional<bool> _timeseriesMayContainMixedData; + boost::optional<bool> _timeseriesUsesExtendedRange; }; } // namespace mongo diff --git a/src/mongo/db/views/view_catalog_helpers.cpp b/src/mongo/db/views/view_catalog_helpers.cpp index 1dbda87d45c..4e47c0900eb 100644 --- a/src/mongo/db/views/view_catalog_helpers.cpp +++ b/src/mongo/db/views/view_catalog_helpers.cpp @@ -150,6 +150,7 @@ StatusWith<ResolvedView> resolveView(OperationContext* opCtx, int depth = 0; boost::optional<bool> mixedData = boost::none; boost::optional<TimeseriesOptions> tsOptions = boost::none; + boost::optional<bool> hasExtendedRange = boost::none; for (; depth < ViewGraph::kMaxViewDepth; depth++) { auto view = catalog->lookupView(opCtx, *resolvedNss); @@ -173,7 +174,8 @@ StatusWith<ResolvedView> resolveView(OperationContext* opCtx, std::move(resolvedPipeline), collation ? std::move(collation.value()) : CollationSpec::kSimpleSpec, tsOptions, - mixedData}); + mixedData, + hasExtendedRange}); } resolvedNss = &view->viewOn(); @@ -193,6 +195,7 @@ StatusWith<ResolvedView> resolveView(OperationContext* opCtx, if (tsCollection) { mixedData = tsCollection->getTimeseriesBucketsMayHaveMixedSchemaData(); tsOptions = tsCollection->getTimeseriesOptions(); + hasExtendedRange = tsCollection->getRequiresTimeseriesExtendedRangeSupport(); } } |