Making Monotonicity an aggregate to use with designated initializers

This commit is contained in:
Mike Kot 2021-09-29 18:01:26 +02:00
parent 340fb049cf
commit 61e0c6208b
18 changed files with 54 additions and 57 deletions

View File

@ -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<typename Transform::FactorTransform, ZeroTransform>)
return { .is_monotonic = true, .is_always_monotonic = true };
if (std::is_same_v<typename Transform::FactorTransform, ZeroTransform>)
{
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.

View File

@ -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<typename Transform::FactorTransform, ZeroTransform>)
return { .is_monotonic = true, .is_always_monotonic = true };
if (std::is_same_v<typename Transform::FactorTransform, ZeroTransform>)
{
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();

View File

@ -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 };
}
};

View File

@ -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<DataTypeNumber<T>>(&type) ||
checkAndGetDataType<DataTypeEnum<T>>(&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<T>)
return {true, true, true};
if constexpr (std::is_floating_point_v<T>)
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<Float64>(std::numeric_limits<T>::max())
&& right_float >= static_cast<Float64>(std::numeric_limits<T>::min())
&& right_float <= static_cast<Float64>(std::numeric_limits<T>::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<UInt64>()) >= 0) == (T(right.get<UInt64>()) >= 0)};
const bool is_monotonic = (T(left.get<UInt64>()) >= 0) == (T(right.get<UInt64>()) >= 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<UInt64>() < 0xFFFF) && (right.isNull() || right.get<UInt64>() >= 0xFFFF)))
|| (which.isInt() && ((left.isNull() || left.get<Int64>() < 0xFFFF) && (right.isNull() || right.get<Int64>() >= 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;

View File

@ -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 };
}
};

View File

@ -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.

View File

@ -46,7 +46,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameAbs>
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 };
}
};

View File

@ -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:

View File

@ -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:

View File

@ -55,7 +55,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameIntExp10>
if (left_float < 0 || right_float > 19)
return {};
return { true };
return { .is_monotonic = true };
}
};

View File

@ -58,7 +58,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameIntExp2>
if (left_float < 0 || right_float > 63)
return {};
return { true };
return { .is_monotonic = true };
}
};

View File

@ -42,7 +42,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameNegate>
static bool has() { return true; }
static IFunction::Monotonicity get(const Field &, const Field &)
{
return { true, false };
return { .is_monotonic = true, .is_positive = false };
}
};

View File

@ -37,7 +37,10 @@ template <>
struct FunctionUnaryArithmeticMonotonicity<NameSign>
{
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)

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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)
{

View File

@ -28,7 +28,9 @@ public:
const TablesWithColumns & tables;
ContextPtr context;
const std::unordered_set<String> & 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 = {};