diff options
Diffstat (limited to 'src/mongo/db/exec/bucket_unpacker.cpp')
-rw-r--r-- | src/mongo/db/exec/bucket_unpacker.cpp | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/src/mongo/db/exec/bucket_unpacker.cpp b/src/mongo/db/exec/bucket_unpacker.cpp index 6a819181df9..02be8fe3d64 100644 --- a/src/mongo/db/exec/bucket_unpacker.cpp +++ b/src/mongo/db/exec/bucket_unpacker.cpp @@ -248,6 +248,11 @@ boost::optional<StringData> checkComparisonPredicateErrors( return "can't handle a computed field"_sd; } + // We must avoid mapping predicates on fields removed by $project. + if (!determineIncludeField(matchExprPath, bucketSpec.behavior(), bucketSpec.fieldSet())) { + return "can't handle a field removed by projection"_sd; + } + const auto isTimeField = (matchExprPath == bucketSpec.timeField()); if (isTimeField && matchExprData.type() != BSONType::Date) { // Users are not allowed to insert non-date measurements into time field. So this query @@ -885,10 +890,8 @@ std::pair<bool, BSONObj> BucketSpec::pushdownPredicate( metaField.map([](StringData s) { return s.toString(); }), // Since we are operating on a collection, not a query-result, // there are no inclusion/exclusion projections we need to apply - // to the buckets before unpacking. - {}, - // And there are no computed projections. - {}, + // to the buckets before unpacking. So we can use default values for the rest of + // the arguments. }, maxSpanSeconds, collationMatchesDefault, @@ -924,7 +927,6 @@ public: int j, const BucketSpec& spec, const std::set<std::string>& unpackFieldsToIncludeExclude, - BucketUnpacker::Behavior behavior, const BSONObj& bucket, const Value& metaValue, bool includeTimeField, @@ -976,7 +978,6 @@ public: int j, const BucketSpec& spec, const std::set<std::string>& unpackFieldsToIncludeExclude, - BucketUnpacker::Behavior behavior, const BSONObj& bucket, const Value& metaValue, bool includeTimeField, @@ -988,7 +989,7 @@ private: BSONObjIterator _timeFieldIter; // Iterators used to unpack the columns of the above bucket that are populated during the reset - // phase according to the provided 'Behavior' and 'BucketSpec'. + // phase according to the provided 'BucketSpec'. std::vector<std::pair<std::string, BSONObjIterator>> _fieldIters; }; @@ -1063,7 +1064,6 @@ void BucketUnpackerV1::extractSingleMeasurement( int j, const BucketSpec& spec, const std::set<std::string>& unpackFieldsToIncludeExclude, - BucketUnpacker::Behavior behavior, const BSONObj& bucket, const Value& metaValue, bool includeTimeField, @@ -1078,7 +1078,7 @@ void BucketUnpackerV1::extractSingleMeasurement( for (auto&& dataElem : dataRegion) { const auto& colName = dataElem.fieldNameStringData(); - if (!determineIncludeField(colName, behavior, unpackFieldsToIncludeExclude)) { + if (!determineIncludeField(colName, spec.behavior(), unpackFieldsToIncludeExclude)) { continue; } auto value = dataElem[targetIdx]; @@ -1110,7 +1110,6 @@ public: int j, const BucketSpec& spec, const std::set<std::string>& unpackFieldsToIncludeExclude, - BucketUnpacker::Behavior behavior, const BSONObj& bucket, const Value& metaValue, bool includeTimeField, @@ -1140,7 +1139,7 @@ private: ColumnStore _timeColumn; // Iterators used to unpack the columns of the above bucket that are populated during the reset - // phase according to the provided 'Behavior' and 'BucketSpec'. + // phase according to the provided 'BucketSpec'. std::vector<ColumnStore> _fieldColumns; // Element count @@ -1200,7 +1199,6 @@ void BucketUnpackerV2::extractSingleMeasurement( int j, const BucketSpec& spec, const std::set<std::string>& unpackFieldsToIncludeExclude, - BucketUnpacker::Behavior behavior, const BSONObj& bucket, const Value& metaValue, bool includeTimeField, @@ -1236,9 +1234,11 @@ std::size_t BucketUnpackerV2::numberOfFields() { BucketSpec::BucketSpec(const std::string& timeField, const boost::optional<std::string>& metaField, const std::set<std::string>& fields, + Behavior behavior, const std::set<std::string>& computedProjections, bool usesExtendedRange) : _fieldSet(fields), + _behavior(behavior), _computedMetaProjFields(computedProjections), _timeField(timeField), _timeFieldHashed(FieldNameHasher().hashedFieldName(_timeField)), @@ -1251,6 +1251,7 @@ BucketSpec::BucketSpec(const std::string& timeField, BucketSpec::BucketSpec(const BucketSpec& other) : _fieldSet(other._fieldSet), + _behavior(other._behavior), _computedMetaProjFields(other._computedMetaProjFields), _timeField(other._timeField), _timeFieldHashed(HashedFieldName{_timeField, other._timeFieldHashed->hash()}), @@ -1263,6 +1264,7 @@ BucketSpec::BucketSpec(const BucketSpec& other) BucketSpec::BucketSpec(BucketSpec&& other) : _fieldSet(std::move(other._fieldSet)), + _behavior(other._behavior), _computedMetaProjFields(std::move(other._computedMetaProjFields)), _timeField(std::move(other._timeField)), _timeFieldHashed(HashedFieldName{_timeField, other._timeFieldHashed->hash()}), @@ -1276,6 +1278,7 @@ BucketSpec::BucketSpec(BucketSpec&& other) BucketSpec& BucketSpec::operator=(const BucketSpec& other) { if (&other != this) { _fieldSet = other._fieldSet; + _behavior = other._behavior; _computedMetaProjFields = other._computedMetaProjFields; _timeField = other._timeField; _timeFieldHashed = HashedFieldName{_timeField, other._timeFieldHashed->hash()}; @@ -1325,8 +1328,8 @@ BucketUnpacker::BucketUnpacker(BucketUnpacker&& other) = default; BucketUnpacker::~BucketUnpacker() = default; BucketUnpacker& BucketUnpacker::operator=(BucketUnpacker&& rhs) = default; -BucketUnpacker::BucketUnpacker(BucketSpec spec, Behavior unpackerBehavior) { - setBucketSpecAndBehavior(std::move(spec), unpackerBehavior); +BucketUnpacker::BucketUnpacker(BucketSpec spec) { + setBucketSpec(std::move(spec)); } void BucketUnpacker::addComputedMetaProjFields(const std::vector<StringData>& computedFieldNames) { @@ -1335,7 +1338,7 @@ void BucketUnpacker::addComputedMetaProjFields(const std::vector<StringData>& co // If we're already specifically including fields, we need to add the computed fields to // the included field set to indicate they're in the output doc. - if (_unpackerBehavior == BucketUnpacker::Behavior::kInclude) { + if (_spec.behavior() == BucketSpec::Behavior::kInclude) { _spec.addIncludeExcludeField(field); } else { // Since exclude is applied after addComputedMetaProjFields, we must erase the new field @@ -1387,7 +1390,6 @@ Document BucketUnpacker::extractSingleMeasurement(int j) { j, _spec, fieldsToIncludeExcludeDuringUnpack(), - _unpackerBehavior, _bucket, _metaValue, _includeTimeField, @@ -1501,10 +1503,10 @@ void BucketUnpacker::reset(BSONObj&& bucket, bool bucketMatchedQuery) { continue; } - // Includes a field when '_unpackerBehavior' is 'kInclude' and it's found in 'fieldSet' or - // _unpackerBehavior is 'kExclude' and it's not found in 'fieldSet'. + // Includes a field when '_spec.behavior()' is 'kInclude' and it's found in 'fieldSet' or + // _spec.behavior() is 'kExclude' and it's not found in 'fieldSet'. if (determineIncludeField( - colName, _unpackerBehavior, fieldsToIncludeExcludeDuringUnpack())) { + colName, _spec.behavior(), fieldsToIncludeExcludeDuringUnpack())) { _unpackingImpl->addField(elem); } } @@ -1555,7 +1557,7 @@ int BucketUnpacker::computeMeasurementCount(const BSONObj& bucket, StringData ti } void BucketUnpacker::determineIncludeTimeField() { - const bool isInclude = _unpackerBehavior == BucketUnpacker::Behavior::kInclude; + const bool isInclude = _spec.behavior() == BucketSpec::Behavior::kInclude; const bool fieldSetContainsTime = _spec.fieldSet().find(_spec.timeField()) != _spec.fieldSet().end(); @@ -1575,22 +1577,21 @@ void BucketUnpacker::eraseMetaFromFieldSetAndDetermineIncludeMeta() { } else if (auto itr = _spec.fieldSet().find(*_spec.metaField()); itr != _spec.fieldSet().end()) { _spec.removeIncludeExcludeField(*_spec.metaField()); - _includeMetaField = _unpackerBehavior == BucketUnpacker::Behavior::kInclude; + _includeMetaField = _spec.behavior() == BucketSpec::Behavior::kInclude; } else { - _includeMetaField = _unpackerBehavior == BucketUnpacker::Behavior::kExclude; + _includeMetaField = _spec.behavior() == BucketSpec::Behavior::kExclude; } } void BucketUnpacker::eraseExcludedComputedMetaProjFields() { - if (_unpackerBehavior == BucketUnpacker::Behavior::kExclude) { + if (_spec.behavior() == BucketSpec::Behavior::kExclude) { for (const auto& field : _spec.fieldSet()) { _spec.eraseFromComputedMetaProjFields(field); } } } -void BucketUnpacker::setBucketSpecAndBehavior(BucketSpec&& bucketSpec, Behavior behavior) { - _unpackerBehavior = behavior; +void BucketUnpacker::setBucketSpec(BucketSpec&& bucketSpec) { _spec = std::move(bucketSpec); eraseMetaFromFieldSetAndDetermineIncludeMeta(); @@ -1616,7 +1617,7 @@ const std::set<std::string>& BucketUnpacker::fieldsToIncludeExcludeDuringUnpack( _unpackFieldsToIncludeExclude = std::set<std::string>(); const auto& metaProjFields = _spec.computedMetaProjFields(); - if (_unpackerBehavior == BucketUnpacker::Behavior::kInclude) { + if (_spec.behavior() == BucketSpec::Behavior::kInclude) { // For include, we unpack fieldSet - metaProjFields. for (auto&& field : _spec.fieldSet()) { if (metaProjFields.find(field) == metaProjFields.cend()) { |