@@ -53,6 +53,7 @@ namespace Setting
5353{
5454 extern const SettingsBool analyze_index_with_space_filling_curves;
5555 extern const SettingsDateTimeOverflowBehavior date_time_overflow_behavior;
56+ extern const SettingsTimezone session_timezone;
5657}
5758
5859namespace ErrorCodes
@@ -1093,7 +1094,7 @@ bool applyFunctionChainToColumn(
10931094 }
10941095
10951096 // And cast it to the argument type of the first function in the chain
1096- auto in_argument_type = getArgumentTypeOfMonotonicFunction (*functions[0 ]);
1097+ auto in_argument_type = removeLowCardinality ( getArgumentTypeOfMonotonicFunction (*functions[0 ]) );
10971098 if (canBeSafelyCast (result_type, in_argument_type))
10981099 {
10991100 result_column = castColumnAccurate ({result_column, result_type, " " }, in_argument_type);
@@ -1122,13 +1123,13 @@ bool applyFunctionChainToColumn(
11221123 if (func->getArgumentTypes ().empty ())
11231124 return false ;
11241125
1125- auto argument_type = getArgumentTypeOfMonotonicFunction (*func);
1126+ auto argument_type = removeLowCardinality ( getArgumentTypeOfMonotonicFunction (*func) );
11261127 if (!canBeSafelyCast (result_type, argument_type))
11271128 return false ;
11281129
11291130 result_column = castColumnAccurate ({result_column, result_type, " " }, argument_type);
1130- result_column = func-> execute ({{result_column, argument_type, " " }}, func->getResultType (), result_column-> size (), /* dry_run = */ false );
1131- result_type = func->getResultType ( );
1131+ result_type = removeLowCardinality ( func->getResultType ());
1132+ result_column = func->execute ({{result_column, argument_type, " " }}, result_type, result_column-> size (), /* dry_run = */ false );
11321133
11331134 // Transforming nullable columns to the nested ones, in case no nulls found
11341135 if (result_column->isNullable ())
@@ -1141,7 +1142,7 @@ bool applyFunctionChainToColumn(
11411142 return false ;
11421143 }
11431144 result_column = result_column_nullable.getNestedColumnPtr ();
1144- result_type = removeNullable (func-> getResultType () );
1145+ result_type = removeNullable (result_type );
11451146 }
11461147 }
11471148 out_column = result_column;
@@ -1903,48 +1904,57 @@ bool KeyCondition::extractMonotonicFunctionsChainFromKey(
19031904 auto func_name = func->function_base ->getName ();
19041905 auto func_base = func->function_base ;
19051906
1906- ColumnsWithTypeAndName arguments;
19071907 ColumnWithTypeAndName const_arg;
19081908 FunctionWithOptionalConstArg::Kind kind = FunctionWithOptionalConstArg::Kind::NO_CONST;
19091909
19101910 if (date_time_parsing_functions.contains (func_name))
19111911 {
1912- const auto & arg_types = func_base->getArgumentTypes ();
1913- if (!arg_types.empty () && isStringOrFixedString (arg_types[0 ]))
1914- func_name = func_name + " OrNull" ;
1915- }
1912+ const auto & func_arg_types = func_base->getArgumentTypes ();
19161913
1917- auto func_builder = FunctionFactory::instance ().tryGet (func_name, context);
1914+ const bool has_string_argument = !func_arg_types.empty () && isStringOrFixedString (func_arg_types[0 ]);
1915+ const bool has_session_timezone = !context->getSettingsRef ()[Setting::session_timezone].value .empty ();
19181916
1919- if (func->children .size () == 1 )
1920- {
1921- arguments.push_back ({nullptr , removeLowCardinality (func->children [0 ]->result_type ), " " });
1917+ // Skipping analysis in case when is requires parsing datetime from string
1918+ // with `session_timezone` specified
1919+ if (has_string_argument && has_session_timezone)
1920+ return false ;
1921+
1922+ // Otherwise, in case when datetime parsing is required, rebuilding the function,
1923+ // to get its "-OrNull" version required for safe parsing, and not failing on
1924+ // values with incorrect format
1925+ if (has_string_argument)
1926+ {
1927+ ColumnsWithTypeAndName new_args;
1928+ for (const auto & type : func->function_base ->getArgumentTypes ())
1929+ new_args.push_back ({nullptr , type, " " });
1930+
1931+ const auto func_builder = FunctionFactory::instance ().tryGet (func_name + " OrNull" , context);
1932+ func_base = func_builder->build (new_args);
1933+ }
19221934 }
1923- else if (func->children .size () == 2 )
1935+
1936+ // For single argument functions, the input may be used as-is, for binary functions,
1937+ // we'll produce a partially applied version of `func` with the reduced arity
1938+ if (func->children .size () == 2 )
19241939 {
19251940 const auto * left = func->children [0 ];
19261941 const auto * right = func->children [1 ];
19271942 if (left->column && isColumnConst (*left->column ))
19281943 {
19291944 const_arg = {left->result_type ->createColumnConst (0 , (*left->column )[0 ]), left->result_type , " " };
1930- arguments.push_back (const_arg);
1931- arguments.push_back ({nullptr , removeLowCardinality (right->result_type ), " " });
19321945 kind = FunctionWithOptionalConstArg::Kind::LEFT_CONST;
19331946 }
19341947 else
19351948 {
19361949 const_arg = {right->result_type ->createColumnConst (0 , (*right->column )[0 ]), right->result_type , " " };
1937- arguments.push_back ({nullptr , removeLowCardinality (left->result_type ), " " });
1938- arguments.push_back (const_arg);
19391950 kind = FunctionWithOptionalConstArg::Kind::RIGHT_CONST;
19401951 }
19411952 }
19421953
1943- auto out_func = func_builder->build (arguments);
19441954 if (kind == FunctionWithOptionalConstArg::Kind::NO_CONST)
1945- out_functions_chain.push_back (out_func );
1955+ out_functions_chain.push_back (func_base );
19461956 else
1947- out_functions_chain.push_back (std::make_shared<FunctionWithOptionalConstArg>(out_func , const_arg, kind));
1957+ out_functions_chain.push_back (std::make_shared<FunctionWithOptionalConstArg>(func_base , const_arg, kind));
19481958 }
19491959
19501960 out_key_column_num = it->second ;
0 commit comments