diff --git a/src/Functions/FunctionCustomWeekToSomething.h b/src/Functions/FunctionCustomWeekToSomething.h index 0fb91532c58..542062151ce 100644 --- a/src/Functions/FunctionCustomWeekToSomething.h +++ b/src/Functions/FunctionCustomWeekToSomething.h @@ -130,20 +130,17 @@ public: Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const override { - IFunction::Monotonicity is_monotonic{true}; - IFunction::Monotonicity is_not_monotonic; + if constexpr (std::is_same_v) + return { .is_monotonic = true, .is_always_monotonic = true }; - if (std::is_same_v) - { - is_monotonic.is_always_monotonic = true; - return is_monotonic; - } + const IFunction::Monotonicity is_monotonic = { .is_monotonic = true }; + const IFunction::Monotonicity is_not_monotonic; /// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone. const DateLUTImpl & date_lut = DateLUT::instance(); if (left.isNull() || right.isNull()) - return is_not_monotonic; + return {}; /// The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them. diff --git a/src/Functions/FunctionDateOrDateTimeToSomething.h b/src/Functions/FunctionDateOrDateTimeToSomething.h index 5f23947ce7d..00678e65364 100644 --- a/src/Functions/FunctionDateOrDateTimeToSomething.h +++ b/src/Functions/FunctionDateOrDateTimeToSomething.h @@ -128,14 +128,11 @@ public: Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const override { - IFunction::Monotonicity is_monotonic { true }; - IFunction::Monotonicity is_not_monotonic; + if constexpr (std::is_same_v) + return { .is_monotonic = true, .is_always_monotonic = true }; - if (std::is_same_v) - { - is_monotonic.is_always_monotonic = true; - return is_monotonic; - } + const IFunction::Monotonicity is_monotonic = { .is_monotonic = true }; + const IFunction::Monotonicity is_not_monotonic; /// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone. const DateLUTImpl & date_lut = DateLUT::instance(); diff --git a/src/Functions/FunctionUnaryArithmetic.h b/src/Functions/FunctionUnaryArithmetic.h index 31227b5b126..a6cb63639ae 100644 --- a/src/Functions/FunctionUnaryArithmetic.h +++ b/src/Functions/FunctionUnaryArithmetic.h @@ -290,7 +290,7 @@ struct PositiveMonotonicity static bool has() { return true; } static IFunction::Monotonicity get(const Field &, const Field &) { - return { true }; + return { .is_monotonic = true }; } }; diff --git a/src/Functions/FunctionsConversion.h b/src/Functions/FunctionsConversion.h index 6ba2c7e02a5..3c4c28e2af0 100644 --- a/src/Functions/FunctionsConversion.h +++ b/src/Functions/FunctionsConversion.h @@ -1954,7 +1954,7 @@ struct PositiveMonotonicity static bool has() { return true; } static IFunction::Monotonicity get(const IDataType &, const Field &, const Field &) { - return { true }; + return { .is_monotonic = true }; } }; @@ -1963,7 +1963,7 @@ struct UnknownMonotonicity static bool has() { return false; } static IFunction::Monotonicity get(const IDataType &, const Field &, const Field &) { - return { false }; + return { }; } }; @@ -1989,13 +1989,13 @@ struct ToNumberMonotonicity /// (Enum has separate case, because it is different data type) if (checkAndGetDataType>(&type) || checkAndGetDataType>(&type)) - return { true, true, true }; + return { .is_monotonic = true, .is_always_monotonic = true }; /// Float cases. /// When converting to Float, the conversion is always monotonic. - if (std::is_floating_point_v) - return {true, true, true}; + if constexpr (std::is_floating_point_v) + return { .is_monotonic = true, .is_always_monotonic = true }; /// If converting from Float, for monotonicity, arguments must fit in range of result type. if (WhichDataType(type).isFloat()) @@ -2010,7 +2010,7 @@ struct ToNumberMonotonicity && left_float <= static_cast(std::numeric_limits::max()) && right_float >= static_cast(std::numeric_limits::min()) && right_float <= static_cast(std::numeric_limits::max())) - return { true }; + return { .is_monotonic = true }; return {}; } @@ -2035,10 +2035,10 @@ struct ToNumberMonotonicity if (size_of_from == size_of_to) { if (from_is_unsigned == to_is_unsigned) - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; if (left_in_first_half == right_in_first_half) - return {true}; + return { .is_monotonic = true }; return {}; } @@ -2047,14 +2047,14 @@ struct ToNumberMonotonicity if (size_of_from < size_of_to) { if (from_is_unsigned == to_is_unsigned) - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; if (!to_is_unsigned) - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; /// signed -> unsigned. If arguments from the same half, then function is monotonic. if (left_in_first_half == right_in_first_half) - return {true}; + return { .is_monotonic = true }; return {}; } @@ -2071,10 +2071,14 @@ struct ToNumberMonotonicity return {}; if (to_is_unsigned) - return {true}; + return { .is_monotonic = true }; else + { // If To is signed, it's possible that the signedness is different after conversion. So we check it explicitly. - return {(T(left.get()) >= 0) == (T(right.get()) >= 0)}; + const bool is_monotonic = (T(left.get()) >= 0) == (T(right.get()) >= 0); + + return { .is_monotonic = is_monotonic }; + } } __builtin_unreachable(); @@ -2089,7 +2093,7 @@ struct ToDateMonotonicity { auto which = WhichDataType(type); if (which.isDateOrDate32() || which.isDateTime() || which.isDateTime64() || which.isInt8() || which.isInt16() || which.isUInt8() || which.isUInt16()) - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; else if ( (which.isUInt() && ((left.isNull() || left.get() < 0xFFFF) && (right.isNull() || right.get() >= 0xFFFF))) || (which.isInt() && ((left.isNull() || left.get() < 0xFFFF) && (right.isNull() || right.get() >= 0xFFFF))) @@ -2097,7 +2101,7 @@ struct ToDateMonotonicity || !type.isValueRepresentedByNumber()) return {}; else - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; } }; @@ -2108,7 +2112,7 @@ struct ToDateTimeMonotonicity static IFunction::Monotonicity get(const IDataType & type, const Field &, const Field &) { if (type.isValueRepresentedByNumber()) - return {true, true, true}; + return { .is_monotonic = true, .is_always_monotonic = true }; else return {}; } @@ -2123,7 +2127,7 @@ struct ToStringMonotonicity static IFunction::Monotonicity get(const IDataType & type, const Field & left, const Field & right) { - IFunction::Monotonicity positive(true, true); + IFunction::Monotonicity positive{ .is_monotonic = true }; IFunction::Monotonicity not_monotonic; const auto * type_ptr = &type; diff --git a/src/Functions/FunctionsRound.h b/src/Functions/FunctionsRound.h index 3474790b8b3..0f5fc020934 100644 --- a/src/Functions/FunctionsRound.h +++ b/src/Functions/FunctionsRound.h @@ -614,7 +614,7 @@ public: Monotonicity getMonotonicityForRange(const IDataType &, const Field &, const Field &) const override { - return { true, true, true }; + return { .is_monotonic = true, .is_always_monotonic = true }; } }; diff --git a/src/Functions/IFunction.h b/src/Functions/IFunction.h index db8a449f2b1..05104b1f896 100644 --- a/src/Functions/IFunction.h +++ b/src/Functions/IFunction.h @@ -250,12 +250,9 @@ public: /// The property of monotonicity for a certain range. struct Monotonicity { - bool is_monotonic = false; /// Is the function monotonous (nondecreasing or nonincreasing). - bool is_positive = true; /// true if the function is nondecreasing, false, if notincreasing. If is_monotonic = false, then it does not matter. + bool is_monotonic = false; /// Is the function monotonous (non-decreasing or non-increasing). + bool is_positive = true; /// true if the function is non-decreasing, false if non-increasing. If is_monotonic = false, then it does not matter. bool is_always_monotonic = false; /// Is true if function is monotonic on the whole input range I - - Monotonicity(bool is_monotonic_ = false, bool is_positive_ = true, bool is_always_monotonic_ = false) - : is_monotonic(is_monotonic_), is_positive(is_positive_), is_always_monotonic(is_always_monotonic_) {} }; /** Get information about monotonicity on a range of values. Call only if hasInformationAboutMonotonicity. diff --git a/src/Functions/abs.cpp b/src/Functions/abs.cpp index 21d92e25d75..f8c68c0ded2 100644 --- a/src/Functions/abs.cpp +++ b/src/Functions/abs.cpp @@ -46,7 +46,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity if ((left_float < 0 && right_float > 0) || (left_float > 0 && right_float < 0)) return {}; - return { true, (left_float > 0) }; + return { .is_monotonic = true, .is_positive = left_float > 0 }; } }; diff --git a/src/Functions/date_trunc.cpp b/src/Functions/date_trunc.cpp index 2455bf41fa7..da6a4839ca0 100644 --- a/src/Functions/date_trunc.cpp +++ b/src/Functions/date_trunc.cpp @@ -143,7 +143,7 @@ public: Monotonicity getMonotonicityForRange(const IDataType &, const Field &, const Field &) const override { - return { true, true, true }; + return { .is_monotonic = true, .is_always_monotonic = true }; } private: diff --git a/src/Functions/fromModifiedJulianDay.cpp b/src/Functions/fromModifiedJulianDay.cpp index 913cdbfb21c..e699547e346 100644 --- a/src/Functions/fromModifiedJulianDay.cpp +++ b/src/Functions/fromModifiedJulianDay.cpp @@ -139,10 +139,7 @@ namespace DB Monotonicity getMonotonicityForRange(const IDataType &, const Field &, const Field &) const override { - return Monotonicity( - true, // is_monotonic - true, // is_positive - true); // is_always_monotonic + return { .is_monotonic = true, .is_always_monotonic = true }; } private: diff --git a/src/Functions/intExp10.cpp b/src/Functions/intExp10.cpp index 9eca25fd79b..abaa17c862b 100644 --- a/src/Functions/intExp10.cpp +++ b/src/Functions/intExp10.cpp @@ -55,7 +55,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity if (left_float < 0 || right_float > 19) return {}; - return { true }; + return { .is_monotonic = true }; } }; diff --git a/src/Functions/intExp2.cpp b/src/Functions/intExp2.cpp index 59b829bbad8..b2c7e80ae4b 100644 --- a/src/Functions/intExp2.cpp +++ b/src/Functions/intExp2.cpp @@ -58,7 +58,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity if (left_float < 0 || right_float > 63) return {}; - return { true }; + return { .is_monotonic = true }; } }; diff --git a/src/Functions/negate.cpp b/src/Functions/negate.cpp index 17a9cbfe055..a378589fe30 100644 --- a/src/Functions/negate.cpp +++ b/src/Functions/negate.cpp @@ -42,7 +42,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity static bool has() { return true; } static IFunction::Monotonicity get(const Field &, const Field &) { - return { true, false }; + return { .is_monotonic = true, .is_positive = false }; } }; diff --git a/src/Functions/sign.cpp b/src/Functions/sign.cpp index 67c56ba0206..5dfe6538b32 100644 --- a/src/Functions/sign.cpp +++ b/src/Functions/sign.cpp @@ -37,7 +37,10 @@ template <> struct FunctionUnaryArithmeticMonotonicity { static bool has() { return true; } - static IFunction::Monotonicity get(const Field &, const Field &) { return {true, true, false}; } + static IFunction::Monotonicity get(const Field &, const Field &) + { + return { .is_monotonic = true }; + } }; void registerFunctionSign(FunctionFactory & factory) diff --git a/src/Functions/toModifiedJulianDay.cpp b/src/Functions/toModifiedJulianDay.cpp index ead2ca826d1..7873baa11af 100644 --- a/src/Functions/toModifiedJulianDay.cpp +++ b/src/Functions/toModifiedJulianDay.cpp @@ -157,10 +157,7 @@ namespace DB Monotonicity getMonotonicityForRange(const IDataType &, const Field &, const Field &) const override { - return Monotonicity( - true, // is_monotonic - true, // is_positive - true); // is_always_monotonic + return { .is_monotonic = true, .is_always_monotonic = true }; } private: diff --git a/src/Functions/toStartOfInterval.cpp b/src/Functions/toStartOfInterval.cpp index 2ad7585fad3..fe7b1188a47 100644 --- a/src/Functions/toStartOfInterval.cpp +++ b/src/Functions/toStartOfInterval.cpp @@ -311,7 +311,7 @@ public: Monotonicity getMonotonicityForRange(const IDataType &, const Field &, const Field &) const override { - return { true, true, true }; + return { .is_monotonic = true, .is_always_monotonic = true }; } private: diff --git a/src/Functions/toTimezone.cpp b/src/Functions/toTimezone.cpp index 8205a62614e..092b79131d8 100644 --- a/src/Functions/toTimezone.cpp +++ b/src/Functions/toTimezone.cpp @@ -66,7 +66,8 @@ public: Monotonicity getMonotonicityForRange(const IDataType & /*type*/, const Field & /*left*/, const Field & /*right*/) const override { - return {is_constant_timezone, is_constant_timezone, is_constant_timezone}; + const bool b = is_constant_timezone; + return { .is_monotonic = b, .is_positive = b, .is_always_monotonic = b }; } private: diff --git a/src/Interpreters/ExpressionJIT.cpp b/src/Interpreters/ExpressionJIT.cpp index 9005b24b044..9203c2182d8 100644 --- a/src/Interpreters/ExpressionJIT.cpp +++ b/src/Interpreters/ExpressionJIT.cpp @@ -239,7 +239,9 @@ public: const IDataType * type_ptr = &type; Field left_mut = left; Field right_mut = right; - Monotonicity result(true, true, true); + + Monotonicity result = { .is_monotonic = true, .is_positive = true, .is_always_monotonic = true }; + /// monotonicity is only defined for unary functions, so the chain must describe a sequence of nested calls for (size_t i = 0; i < nested_functions.size(); ++i) { diff --git a/src/Interpreters/MonotonicityCheckVisitor.h b/src/Interpreters/MonotonicityCheckVisitor.h index 350318047c7..a25fbf26420 100644 --- a/src/Interpreters/MonotonicityCheckVisitor.h +++ b/src/Interpreters/MonotonicityCheckVisitor.h @@ -28,7 +28,9 @@ public: const TablesWithColumns & tables; ContextPtr context; const std::unordered_set & group_by_function_hashes; - Monotonicity monotonicity{true, true, true}; + + Monotonicity monotonicity = { .is_monotonic = true, .is_positive = true, .is_always_monotonic = true }; + ASTIdentifier * identifier = nullptr; DataTypePtr arg_data_type = {};