@@ -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
@@ -1048,7 +1049,7 @@ bool applyFunctionChainToColumn(
10481049 }
10491050
10501051 // And cast it to the argument type of the first function in the chain
1051- auto in_argument_type = getArgumentTypeOfMonotonicFunction (*functions[0 ]);
1052+ auto in_argument_type = removeLowCardinality ( getArgumentTypeOfMonotonicFunction (*functions[0 ]) );
10521053 if (canBeSafelyCast (result_type, in_argument_type))
10531054 {
10541055 result_column = castColumnAccurate ({result_column, result_type, " " }, in_argument_type);
@@ -1077,13 +1078,13 @@ bool applyFunctionChainToColumn(
10771078 if (func->getArgumentTypes ().empty ())
10781079 return false ;
10791080
1080- auto argument_type = getArgumentTypeOfMonotonicFunction (*func);
1081+ auto argument_type = removeLowCardinality ( getArgumentTypeOfMonotonicFunction (*func) );
10811082 if (!canBeSafelyCast (result_type, argument_type))
10821083 return false ;
10831084
10841085 result_column = castColumnAccurate ({result_column, result_type, " " }, argument_type);
1085- result_column = func-> execute ({{result_column, argument_type, " " }}, func->getResultType (), result_column-> size (), /* dry_run = */ false );
1086- result_type = func->getResultType ( );
1086+ result_type = removeLowCardinality ( func->getResultType ());
1087+ result_column = func->execute ({{result_column, argument_type, " " }}, result_type, result_column-> size (), /* dry_run = */ false );
10871088
10881089 // Transforming nullable columns to the nested ones, in case no nulls found
10891090 if (result_column->isNullable ())
@@ -1096,7 +1097,7 @@ bool applyFunctionChainToColumn(
10961097 return false ;
10971098 }
10981099 result_column = result_column_nullable.getNestedColumnPtr ();
1099- result_type = removeNullable (func-> getResultType () );
1100+ result_type = removeNullable (result_type );
11001101 }
11011102 }
11021103 out_column = result_column;
@@ -1854,48 +1855,57 @@ bool KeyCondition::extractMonotonicFunctionsChainFromKey(
18541855 auto func_name = func->function_base ->getName ();
18551856 auto func_base = func->function_base ;
18561857
1857- ColumnsWithTypeAndName arguments;
18581858 ColumnWithTypeAndName const_arg;
18591859 FunctionWithOptionalConstArg::Kind kind = FunctionWithOptionalConstArg::Kind::NO_CONST;
18601860
18611861 if (date_time_parsing_functions.contains (func_name))
18621862 {
1863- const auto & arg_types = func_base->getArgumentTypes ();
1864- if (!arg_types.empty () && isStringOrFixedString (arg_types[0 ]))
1865- func_name = func_name + " OrNull" ;
1866- }
1863+ const auto & func_arg_types = func_base->getArgumentTypes ();
18671864
1868- auto func_builder = FunctionFactory::instance ().tryGet (func_name, context);
1865+ const bool has_string_argument = !func_arg_types.empty () && isStringOrFixedString (func_arg_types[0 ]);
1866+ const bool has_session_timezone = !context->getSettingsRef ()[Setting::session_timezone].value .empty ();
18691867
1870- if (func->children .size () == 1 )
1871- {
1872- arguments.push_back ({nullptr , removeLowCardinality (func->children [0 ]->result_type ), " " });
1868+ // Skipping analysis in case when is requires parsing datetime from string
1869+ // with `session_timezone` specified
1870+ if (has_string_argument && has_session_timezone)
1871+ return false ;
1872+
1873+ // Otherwise, in case when datetime parsing is required, rebuilding the function,
1874+ // to get its "-OrNull" version required for safe parsing, and not failing on
1875+ // values with incorrect format
1876+ if (has_string_argument)
1877+ {
1878+ ColumnsWithTypeAndName new_args;
1879+ for (const auto & type : func->function_base ->getArgumentTypes ())
1880+ new_args.push_back ({nullptr , type, " " });
1881+
1882+ const auto func_builder = FunctionFactory::instance ().tryGet (func_name + " OrNull" , context);
1883+ func_base = func_builder->build (new_args);
1884+ }
18731885 }
1874- else if (func->children .size () == 2 )
1886+
1887+ // For single argument functions, the input may be used as-is, for binary functions,
1888+ // we'll produce a partially applied version of `func` with the reduced arity
1889+ if (func->children .size () == 2 )
18751890 {
18761891 const auto * left = func->children [0 ];
18771892 const auto * right = func->children [1 ];
18781893 if (left->column && isColumnConst (*left->column ))
18791894 {
18801895 const_arg = {left->result_type ->createColumnConst (0 , (*left->column )[0 ]), left->result_type , " " };
1881- arguments.push_back (const_arg);
1882- arguments.push_back ({nullptr , removeLowCardinality (right->result_type ), " " });
18831896 kind = FunctionWithOptionalConstArg::Kind::LEFT_CONST;
18841897 }
18851898 else
18861899 {
18871900 const_arg = {right->result_type ->createColumnConst (0 , (*right->column )[0 ]), right->result_type , " " };
1888- arguments.push_back ({nullptr , removeLowCardinality (left->result_type ), " " });
1889- arguments.push_back (const_arg);
18901901 kind = FunctionWithOptionalConstArg::Kind::RIGHT_CONST;
18911902 }
18921903 }
18931904
1894- auto out_func = func_builder->build (arguments);
18951905 if (kind == FunctionWithOptionalConstArg::Kind::NO_CONST)
1896- out_functions_chain.push_back (out_func );
1906+ out_functions_chain.push_back (func_base );
18971907 else
1898- out_functions_chain.push_back (std::make_shared<FunctionWithOptionalConstArg>(out_func , const_arg, kind));
1908+ out_functions_chain.push_back (std::make_shared<FunctionWithOptionalConstArg>(func_base , const_arg, kind));
18991909 }
19001910
19011911 out_key_column_num = it->second ;
0 commit comments