diff options
| author | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-18 17:02:53 -0300 |
|---|---|---|
| committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-18 17:02:53 -0300 |
| commit | 959575a5ca598bf5f37fb5cebe7ed1d80d3d71f7 (patch) | |
| tree | acc8d60aedb12b70048e676e8a7349deb0010db8 /src/mongo/db/pipeline/window_function | |
| parent | 76588293975fc059cf076779e4283e6ffaf8afff (diff) | |
New upstream version 6.0.20upstream
Diffstat (limited to 'src/mongo/db/pipeline/window_function')
7 files changed, 65 insertions, 46 deletions
diff --git a/src/mongo/db/pipeline/window_function/partition_iterator.cpp b/src/mongo/db/pipeline/window_function/partition_iterator.cpp index 83925b862b3..6188845d516 100644 --- a/src/mongo/db/pipeline/window_function/partition_iterator.cpp +++ b/src/mongo/db/pipeline/window_function/partition_iterator.cpp @@ -205,15 +205,6 @@ optional<int> numericBound(WindowBounds::Bound<int> bound) { bound); } -// Assumes both arguments are numeric, and performs Decimal128 addition on them. -Value decimalAdd(const Value& left, const Value& right) { - // Widening to Decimal128 is a convenient way to avoid having many cases for different numeric - // types. The 'threshold' values we compute are only used to choose a set of documents; the - // user can't observe the type. - return Value(left.coerceToDecimal().add(right.coerceToDecimal())); -} - - } // namespace optional<std::pair<int, int>> PartitionIterator::getEndpointsRangeBased( @@ -247,7 +238,18 @@ optional<std::pair<int, int>> PartitionIterator::getEndpointsRangeBased( dateAdd(base.coerceToDate(), *range.unit, delta.coerceToInt(), TimeZone())}; } else { tassert(5429406, "Range-based bounds are specified as a number", delta.numeric()); - return decimalAdd(base, delta); + if (base.getType() == BSONType::NumberDouble) { + // When we compare a double and a Decimal128, we convert the Decimal128 to double + // and compare two double values. Since converting a double to Decimal128 is + // expensive and since during the comparison we will convert the Decimal128 to + // double, we compute the threshold as double from the beginning when the base + // value is already a double. + return Value(base.getDouble() + delta.coerceToDouble()); + } + // Widening to Decimal128 is a convenient way to avoid having many cases for different + // numeric types. The 'threshold' values we compute are only used to choose a set of + // documents; the user can't observe the type. + return Value(base.coerceToDecimal().add(delta.coerceToDecimal())); } }; auto hasExpectedType = [&](const Value& v) -> bool { diff --git a/src/mongo/db/pipeline/window_function/window_bounds.cpp b/src/mongo/db/pipeline/window_function/window_bounds.cpp index dd082135e02..7ede49d0065 100644 --- a/src/mongo/db/pipeline/window_function/window_bounds.cpp +++ b/src/mongo/db/pipeline/window_function/window_bounds.cpp @@ -63,12 +63,19 @@ WindowBounds::Bound<T> parseBound(ExpressionContext* expCtx, } template <class T> -Value serializeBound(const WindowBounds::Bound<T>& bound) { +Value serializeBound(const WindowBounds::Bound<T>& bound, + const SerializationOptions& opts, + const Value& representativeValue) { return stdx::visit( visit_helper::Overloaded{ - [](const WindowBounds::Unbounded&) { return Value(WindowBounds::kValUnbounded); }, - [](const WindowBounds::Current&) { return Value(WindowBounds::kValCurrent); }, - [](const T& n) { return Value(n); }, + [&](const WindowBounds::Unbounded&) { return Value(WindowBounds::kValUnbounded); }, + [&](const WindowBounds::Current&) { return Value(WindowBounds::kValCurrent); }, + [&](const T& n) { + // If not "unbounded" or "current", n must be a literal constant + // The upper bound must be greater than the lower bound. We override the + // representative value to meet this constraint. + return opts.serializeLiteral(n, representativeValue); + }, }, bound); } @@ -215,22 +222,31 @@ WindowBounds WindowBounds::parse(BSONObj args, uassert(5339902, "Range-based bounds require sortBy a single field", sortBy && sortBy->size() == 1); + const SortPattern::SortPatternPart& part = *sortBy->begin(); + uassert(8947400, + "Range-based bounds require a non-expression sortBy", + part.fieldPath && !part.expression); + uassert(8947401, "Range-based bounds require an ascending sortBy", part.isAscending); return bounds; } } -void WindowBounds::serialize(MutableDocument& args) const { +void WindowBounds::serialize(MutableDocument& args, const SerializationOptions& opts) const { stdx::visit( visit_helper::Overloaded{ [&](const DocumentBased& docBounds) { args[kArgDocuments] = Value{std::vector<Value>{ - serializeBound(docBounds.lower), - serializeBound(docBounds.upper), + serializeBound( + docBounds.lower, opts, /* representative value, if needed */ Value(0LL)), + serializeBound( + docBounds.upper, opts, /* representative value, if needed */ Value(1LL)), }}; }, [&](const RangeBased& rangeBounds) { args[kArgRange] = Value{std::vector<Value>{ - serializeBound(rangeBounds.lower), - serializeBound(rangeBounds.upper), + serializeBound( + rangeBounds.lower, opts, /* representative value, if needed */ Value(0LL)), + serializeBound( + rangeBounds.upper, opts, /* representative value, if needed */ Value(1LL)), }}; if (rangeBounds.unit) { args[kArgUnit] = Value{serializeTimeUnit(*rangeBounds.unit)}; diff --git a/src/mongo/db/pipeline/window_function/window_bounds.h b/src/mongo/db/pipeline/window_function/window_bounds.h index 6999f8fcdbc..90d0adf0371 100644 --- a/src/mongo/db/pipeline/window_function/window_bounds.h +++ b/src/mongo/db/pipeline/window_function/window_bounds.h @@ -121,7 +121,7 @@ struct WindowBounds { const boost::optional<SortPattern>& sortBy, ExpressionContext* expCtx); - void serialize(MutableDocument& args) const; + void serialize(MutableDocument& args, const SerializationOptions& opts) const; }; } // namespace mongo diff --git a/src/mongo/db/pipeline/window_function/window_function_expression.cpp b/src/mongo/db/pipeline/window_function/window_function_expression.cpp index 0d43689c977..a46bac72dfa 100644 --- a/src/mongo/db/pipeline/window_function/window_function_expression.cpp +++ b/src/mongo/db/pipeline/window_function/window_function_expression.cpp @@ -310,12 +310,12 @@ boost::intrusive_ptr<Expression> ExpressionFirstLast::parse( template <typename WindowFunctionN, typename AccumulatorNType> Value ExpressionN<WindowFunctionN, AccumulatorNType>::serialize( - boost::optional<ExplainOptions::Verbosity> explain) const { + const SerializationOptions& opts) const { auto acc = buildAccumulatorOnly(); - MutableDocument result(acc->serialize(nExpr, _input, static_cast<bool>(explain))); + MutableDocument result(acc->serialize(nExpr, _input, opts)); MutableDocument windowField; - _bounds.serialize(windowField); + _bounds.serialize(windowField, opts); result[kWindowArg] = windowField.freezeToValue(); return result.freezeToValue(); } diff --git a/src/mongo/db/pipeline/window_function/window_function_expression.h b/src/mongo/db/pipeline/window_function/window_function_expression.h index 261d4212fe5..b14a81d1ae3 100644 --- a/src/mongo/db/pipeline/window_function/window_function_expression.h +++ b/src/mongo/db/pipeline/window_function/window_function_expression.h @@ -189,17 +189,16 @@ public: } }; - virtual Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const { + virtual Value serialize(const SerializationOptions& opts) const { MutableDocument args; - args[_accumulatorName] = _input->serialize(static_cast<bool>(explain)); + args[_accumulatorName] = _input->serialize(opts); MutableDocument windowField; - _bounds.serialize(windowField); + _bounds.serialize(windowField, opts); args[kWindowArg] = windowField.freezeToValue(); return args.freezeToValue(); } - protected: ExpressionContext* _expCtx; std::string _accumulatorName; @@ -326,9 +325,9 @@ public: << " is not supported as a removable window function"); } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final { + Value serialize(const SerializationOptions& opts) const final { MutableDocument args; - args.addField(_accumulatorName, Value(_input->serialize(static_cast<bool>(explain)))); + args.addField(_accumulatorName, Value(_input->serialize(opts))); return args.freezeToValue(); } }; @@ -444,7 +443,7 @@ public: << " is not supported with a removable window"); } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final { + Value serialize(const SerializationOptions& opts) const final { MutableDocument args; args.addField(_accumulatorName, Value(Document())); return args.freezeToValue(); @@ -493,15 +492,17 @@ public: << " is not supported with a removable window"); } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final { + Value serialize(const SerializationOptions& opts) const final { MutableDocument subObj; tassert(5433604, "ExpMovingAvg neither N nor alpha was set", _N || _alpha); if (_N) { - subObj[kNArg] = Value(_N.get()); + subObj[kNArg] = opts.serializeLiteral(_N.get()); } else { - subObj[kAlphaArg] = Value(_alpha.get()); + // Alpha must be between zero and one (exclusive), so choose a legal representative + // value if applicable. + subObj[kAlphaArg] = opts.serializeLiteral(_alpha.get(), Value(0.1)); } - subObj[kInputArg] = _input->serialize(static_cast<bool>(explain)); + subObj[kInputArg] = _input->serialize(opts); MutableDocument outerObj; outerObj[kAccName] = subObj.freezeToValue(); return outerObj.freezeToValue(); @@ -528,15 +529,15 @@ public: return _unit; } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final { + Value serialize(const SerializationOptions& opts) const final { MutableDocument result; - result[_accumulatorName][kArgInput] = _input->serialize(static_cast<bool>(explain)); + result[_accumulatorName][kArgInput] = _input->serialize(opts); if (_unit) { result[_accumulatorName][kArgUnit] = Value(serializeTimeUnit(*_unit)); } MutableDocument windowField; - _bounds.serialize(windowField); + _bounds.serialize(windowField, opts); result[kWindowArg] = windowField.freezeToValue(); return result.freezeToValue(); } @@ -810,9 +811,9 @@ public: MONGO_UNREACHABLE_TASSERT(5490705); } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final { + Value serialize(const SerializationOptions& opts) const final { MutableDocument args; - args.addField(_accumulatorName, Value(_input->serialize(static_cast<bool>(explain)))); + args.addField(_accumulatorName, Value(_input->serialize(opts))); return args.freezeToValue(); } }; @@ -904,7 +905,7 @@ public: nExpr(std::move(nExpr)), sortPattern(std::move(sortPattern)) {} - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final; + Value serialize(const SerializationOptions& opts) const final; boost::intrusive_ptr<AccumulatorState> buildAccumulatorOnly() const final; diff --git a/src/mongo/db/pipeline/window_function/window_function_shift.cpp b/src/mongo/db/pipeline/window_function/window_function_shift.cpp index c74424e74e7..0ae15c4e3f0 100644 --- a/src/mongo/db/pipeline/window_function/window_function_shift.cpp +++ b/src/mongo/db/pipeline/window_function/window_function_shift.cpp @@ -119,12 +119,12 @@ boost::intrusive_ptr<Expression> ExpressionShift::parse(BSONObj obj, return shiftExpr; } -Value ExpressionShift::serialize(boost::optional<ExplainOptions::Verbosity> explain) const { +Value ExpressionShift::serialize(const SerializationOptions& opts) const { MutableDocument args; - args.addField(kByArg, Value(_offset)); - args.addField(kOutputArg, _input->serialize(static_cast<bool>(explain))); - args.addField(kDefaultArg, _defaultVal.get_value_or(mongo::Value(BSONNULL))); - + args.addField(kByArg, opts.serializeLiteral(_offset)); + args.addField(kOutputArg, _input->serialize(opts)); + args.addField(kDefaultArg, + opts.serializeLiteral(_defaultVal.get_value_or(mongo::Value(BSONNULL)))); MutableDocument windowFun; windowFun.addField(_accumulatorName, args.freezeToValue()); return windowFun.freezeToValue(); diff --git a/src/mongo/db/pipeline/window_function/window_function_shift.h b/src/mongo/db/pipeline/window_function/window_function_shift.h index 99a45dd3f84..649e90ce7e4 100644 --- a/src/mongo/db/pipeline/window_function/window_function_shift.h +++ b/src/mongo/db/pipeline/window_function/window_function_shift.h @@ -68,7 +68,7 @@ public: MONGO_UNREACHABLE_TASSERT(5424302); } - Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final; + Value serialize(const SerializationOptions& opts) const final; private: static boost::intrusive_ptr<Expression> parseShiftArgs(BSONObj obj, |
