33#include < DataTypes/DataTypeDate32.h>
44#include < DataTypes/DataTypeDateTime.h>
55#include < DataTypes/DataTypeDateTime64.h>
6+ #include < DataTypes/DataTypeLowCardinality.h>
7+ #include < DataTypes/DataTypeNullable.h>
8+ #include < DataTypes/DataTypeString.h>
69#include < Functions/CustomWeekTransforms.h>
710#include < Functions/IFunction.h>
811#include < Functions/TransformDateTime64.h>
@@ -29,35 +32,64 @@ class IFunctionCustomWeek : public IFunction
2932 bool useDefaultImplementationForConstants () const override { return true ; }
3033 ColumnNumbers getArgumentsThatAreAlwaysConstant () const override { return {1 , 2 }; }
3134
35+ bool canBeExecutedOnDefaultArguments () const override
36+ {
37+ // / String default is empty (not parseable as DateTime), so avoid executing on LC default dictionary key
38+ if constexpr (Transform::value_may_be_string)
39+ return false ;
40+
41+ return true ;
42+ }
43+
3244 bool hasInformationAboutMonotonicity () const override { return true ; }
3345
3446 Monotonicity getMonotonicityForRange (const IDataType & type, const Field & left, const Field & right) const override
3547 {
48+ const IDataType * type_ptr = &type;
49+
50+ if (const auto * lc_type = checkAndGetDataType<DataTypeLowCardinality>(type_ptr))
51+ type_ptr = lc_type->getDictionaryType ().get ();
52+
53+ if (const auto * nullable_type = checkAndGetDataType<DataTypeNullable>(type_ptr))
54+ type_ptr = nullable_type->getNestedType ().get ();
55+
56+ const IFunction::Monotonicity is_not_monotonic;
57+
58+ // / Parsing of String arguments is not monotonic w.r.t. String ordering
59+ if (checkAndGetDataType<DataTypeString>(type_ptr))
60+ return is_not_monotonic;
61+
3662 if constexpr (std::is_same_v<typename Transform::FactorTransform, ZeroTransform>)
3763 return {.is_monotonic = true , .is_always_monotonic = true };
3864
65+ if (left.isNull () || right.isNull ())
66+ return is_not_monotonic;
67+
3968 const IFunction::Monotonicity is_monotonic = {.is_monotonic = true };
40- const IFunction::Monotonicity is_not_monotonic;
4169
4270 // / This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone.
4371 const DateLUTImpl & date_lut = DateLUT::instance ();
4472
45- if (left.isNull () || right.isNull ())
46- return {};
47-
4873 // / The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them.
4974
50- if (checkAndGetDataType<DataTypeDate>(&type ))
75+ if (checkAndGetDataType<DataTypeDate>(type_ptr ))
5176 {
5277 return Transform::FactorTransform::execute (UInt16 (left.safeGet <UInt64>()), date_lut)
5378 == Transform::FactorTransform::execute (UInt16 (right.safeGet <UInt64>()), date_lut)
5479 ? is_monotonic
5580 : is_not_monotonic;
5681 }
5782
58- if (checkAndGetDataType<DataTypeDateTime64>(&type ))
83+ if (checkAndGetDataType<DataTypeDate32>(type_ptr ))
5984 {
85+ return Transform::FactorTransform::execute (Int32 (left.safeGet <Int32>()), date_lut)
86+ == Transform::FactorTransform::execute (Int32 (right.safeGet <Int32>()), date_lut)
87+ ? is_monotonic
88+ : is_not_monotonic;
89+ }
6090
91+ if (checkAndGetDataType<DataTypeDateTime64>(type_ptr))
92+ {
6193 const auto & left_date_time = left.safeGet <DateTime64>();
6294 TransformDateTime64<typename Transform::FactorTransform> transformer_left (left_date_time.getScale ());
6395
@@ -70,10 +102,15 @@ class IFunctionCustomWeek : public IFunction
70102 : is_not_monotonic;
71103 }
72104
73- return Transform::FactorTransform::execute (UInt32 (left.safeGet <UInt64>()), date_lut)
74- == Transform::FactorTransform::execute (UInt32 (right.safeGet <UInt64>()), date_lut)
75- ? is_monotonic
76- : is_not_monotonic;
105+ if (checkAndGetDataType<DataTypeDateTime>(type_ptr))
106+ {
107+ return Transform::FactorTransform::execute (UInt32 (left.safeGet <UInt64>()), date_lut)
108+ == Transform::FactorTransform::execute (UInt32 (right.safeGet <UInt64>()), date_lut)
109+ ? is_monotonic
110+ : is_not_monotonic;
111+ }
112+
113+ return is_not_monotonic;
77114 }
78115
79116protected:
0 commit comments