Commit d8c695ea authored by Alexander Barkov's avatar Alexander Barkov

MDEV-11615 Split Item_hybrid_func::fix_attributes into virtual methods in Type_handler

parent 4e23bfa1
...@@ -3108,12 +3108,11 @@ void Item_func_case::fix_length_and_dec() ...@@ -3108,12 +3108,11 @@ void Item_func_case::fix_length_and_dec()
set_handler_by_field_type(agg_field_type(agg, nagg, true)); set_handler_by_field_type(agg_field_type(agg, nagg, true));
if (Item_func_case::result_type() == STRING_RESULT) if (fix_attributes(agg, nagg))
{
if (count_string_result_length(Item_func_case::field_type(), agg, nagg))
return; return;
/* /*
Copy all THEN and ELSE items back to args[] array. Copy all modified THEN and ELSE items back to args[] array.
Some of the items might have been changed to Item_func_conv_charset. Some of the items might have been changed to Item_func_conv_charset.
*/ */
for (nagg= 0 ; nagg < ncases / 2 ; nagg++) for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
...@@ -3121,11 +3120,6 @@ void Item_func_case::fix_length_and_dec() ...@@ -3121,11 +3120,6 @@ void Item_func_case::fix_length_and_dec()
if (else_expr_num != -1) if (else_expr_num != -1)
change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]); change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
}
else
{
fix_attributes(agg, nagg);
}
/* /*
Aggregate first expression and all WHEN expression types Aggregate first expression and all WHEN expression types
...@@ -3405,31 +3399,12 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) ...@@ -3405,31 +3399,12 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
} }
void Item_hybrid_func::fix_attributes(Item **items, uint nitems) bool Item_hybrid_func::fix_attributes(Item **items, uint nitems)
{ {
switch (Item_hybrid_func::result_type()) { bool rc= Item_hybrid_func::type_handler()->
case STRING_RESULT: Item_hybrid_func_fix_attributes(current_thd, this, items, nitems);
if (count_string_result_length(Item_hybrid_func::field_type(), DBUG_ASSERT(!rc || current_thd->is_error());
items, nitems)) return rc;
return;
break;
case DECIMAL_RESULT:
collation.set_numeric();
count_decimal_length(items, nitems);
break;
case REAL_RESULT:
collation.set_numeric();
count_real_length(items, nitems);
break;
case INT_RESULT:
collation.set_numeric();
count_only_length(items, nitems);
decimals= 0;
break;
case ROW_RESULT:
case TIME_RESULT:
DBUG_ASSERT(0);
}
} }
/**************************************************************************** /****************************************************************************
......
...@@ -567,30 +567,6 @@ void Item_udf_func::fix_num_length_and_dec() ...@@ -567,30 +567,6 @@ void Item_udf_func::fix_num_length_and_dec()
} }
/**
Count max_length and decimals for temporal functions.
@param item Argument array
@param nitems Number of arguments in the array.
@retval False on success, true on error.
*/
void Item_func::count_datetime_length(enum_field_types field_type_arg,
Item **item, uint nitems)
{
unsigned_flag= 0;
decimals= 0;
if (field_type_arg != MYSQL_TYPE_DATE)
{
for (uint i= 0; i < nitems; i++)
set_if_bigger(decimals, item[i]->decimals);
}
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
uint len= decimals ? (decimals + 1) : 0;
len+= mysql_temporal_int_part_length(field_type_arg);
fix_char_length(len);
}
/** /**
Set max_length/decimals of function if function is fixed point and Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones. result length/precision depends on argument ones.
...@@ -665,7 +641,7 @@ void Item_func::count_real_length(Item **items, uint nitems) ...@@ -665,7 +641,7 @@ void Item_func::count_real_length(Item **items, uint nitems)
/** /**
Calculate max_length and decimals for STRING_RESULT functions. Calculate max_length and decimals for string functions.
@param field_type Field type. @param field_type Field type.
@param items Argument array. @param items Argument array.
...@@ -673,18 +649,13 @@ void Item_func::count_real_length(Item **items, uint nitems) ...@@ -673,18 +649,13 @@ void Item_func::count_real_length(Item **items, uint nitems)
@retval False on success, true on error. @retval False on success, true on error.
*/ */
bool Item_func::count_string_result_length(enum_field_types field_type_arg, bool Item_func::count_string_length(Item **items, uint nitems)
Item **items, uint nitems)
{ {
DBUG_ASSERT(!is_temporal_type(field_type()));
if (agg_arg_charsets_for_string_result(collation, items, nitems, 1)) if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
return true; return true;
if (is_temporal_type(field_type_arg))
count_datetime_length(field_type_arg, items, nitems);
else
{
count_only_length(items, nitems); count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0; decimals= max_length ? NOT_FIXED_DEC : 0;
}
return false; return false;
} }
......
...@@ -45,11 +45,49 @@ class Item_func :public Item_func_or_sum ...@@ -45,11 +45,49 @@ class Item_func :public Item_func_or_sum
void count_only_length(Item **item, uint nitems); void count_only_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems); void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems); void count_decimal_length(Item **item, uint nitems);
void count_datetime_length(enum_field_types field_type, bool count_string_length(Item **item, uint nitems);
Item **item, uint nitems); uint count_max_decimals(Item **item, uint nitems)
bool count_string_result_length(enum_field_types field_type, {
Item **item, uint nitems); uint res= 0;
for (uint i= 0; i < nitems; i++)
set_if_bigger(res, item[i]->decimals);
return res;
}
public: public:
void aggregate_attributes_int(Item **items, uint nitems)
{
collation.set_numeric();
count_only_length(items, nitems);
decimals= 0;
}
void aggregate_attributes_real(Item **items, uint nitems)
{
collation.set_numeric();
count_real_length(items, nitems);
}
void aggregate_attributes_decimal(Item **items, uint nitems)
{
collation.set_numeric();
count_decimal_length(items, nitems);
}
bool aggregate_attributes_string(Item **item, uint nitems)
{
return count_string_length(item, nitems);
}
void set_attributes_temporal(uint int_part_length, uint dec)
{
collation.set_numeric();
unsigned_flag= 0;
decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS);
uint length= decimals + int_part_length + (dec ? 1 : 0);
fix_char_length(length);
}
void aggregate_attributes_temporal(uint int_part_length,
Item **item, uint nitems)
{
set_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
}
table_map not_null_tables_cache; table_map not_null_tables_cache;
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
...@@ -389,7 +427,7 @@ class Item_hybrid_func: public Item_func, ...@@ -389,7 +427,7 @@ class Item_hybrid_func: public Item_func,
public Type_handler_hybrid_field_type public Type_handler_hybrid_field_type
{ {
protected: protected:
void fix_attributes(Item **item, uint nitems); bool fix_attributes(Item **item, uint nitems);
public: public:
Item_hybrid_func(THD *thd): Item_func(thd) { } Item_hybrid_func(THD *thd): Item_func(thd) { }
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { } Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
......
...@@ -888,6 +888,79 @@ Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const ...@@ -888,6 +888,79 @@ Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const
return new (thd->mem_root) Item_cache_temporal(thd, item->field_type()); return new (thd->mem_root) Item_cache_temporal(thd, item->field_type());
} }
/*************************************************************************/
bool Type_handler_int_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_int(items, nitems);
return false;
}
bool Type_handler_real_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_real(items, nitems);
return false;
}
bool Type_handler_decimal_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_decimal(items, nitems);
return false;
}
bool Type_handler_string_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
return func->aggregate_attributes_string(items, nitems);
}
bool Type_handler_date_common::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->set_attributes_temporal(MAX_DATE_WIDTH, 0);
return false;
}
bool Type_handler_time_common::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_temporal(MIN_TIME_WIDTH, items, nitems);
return false;
}
bool Type_handler_datetime_common::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
return false;
}
bool Type_handler_timestamp_common::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
return false;
}
/*************************************************************************/ /*************************************************************************/
/** /**
......
...@@ -28,6 +28,7 @@ class Item; ...@@ -28,6 +28,7 @@ class Item;
class Item_cache; class Item_cache;
class Item_sum_hybrid; class Item_sum_hybrid;
class Item_func_hex; class Item_func_hex;
class Item_hybrid_func;
class Item_func_hybrid_field_type; class Item_func_hybrid_field_type;
class Item_func_between; class Item_func_between;
class Item_func_in; class Item_func_in;
...@@ -298,6 +299,9 @@ class Type_handler ...@@ -298,6 +299,9 @@ class Type_handler
bool no_conversions) const= 0; bool no_conversions) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0; virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0; virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items,
uint nitems) const= 0;
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0; virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item, virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const= 0; String *str) const= 0;
...@@ -391,6 +395,12 @@ class Type_handler_row: public Type_handler ...@@ -391,6 +395,12 @@ class Type_handler_row: public Type_handler
} }
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const
{
DBUG_ASSERT(0);
return true;
}
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -473,6 +483,8 @@ class Type_handler_real_result: public Type_handler_numeric ...@@ -473,6 +483,8 @@ class Type_handler_real_result: public Type_handler_numeric
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
...@@ -513,6 +525,8 @@ class Type_handler_decimal_result: public Type_handler_numeric ...@@ -513,6 +525,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
...@@ -551,6 +565,8 @@ class Type_handler_int_result: public Type_handler_numeric ...@@ -551,6 +565,8 @@ class Type_handler_int_result: public Type_handler_numeric
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
...@@ -626,6 +642,8 @@ class Type_handler_string_result: public Type_handler ...@@ -626,6 +642,8 @@ class Type_handler_string_result: public Type_handler
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
...@@ -778,6 +796,8 @@ class Type_handler_time_common: public Type_handler_temporal_result ...@@ -778,6 +796,8 @@ class Type_handler_time_common: public Type_handler_temporal_result
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
}; };
...@@ -813,62 +833,85 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result ...@@ -813,62 +833,85 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
}; };
class Type_handler_date: public Type_handler_temporal_with_date class Type_handler_date_common: public Type_handler_temporal_with_date
{ {
public: public:
virtual ~Type_handler_date() {} virtual ~Type_handler_date_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATE; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
};
class Type_handler_date: public Type_handler_date_common
{
public:
virtual ~Type_handler_date() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
}; };
class Type_handler_newdate: public Type_handler_temporal_with_date class Type_handler_newdate: public Type_handler_date_common
{ {
public: public:
virtual ~Type_handler_newdate() {} virtual ~Type_handler_newdate() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
}; };
class Type_handler_datetime: public Type_handler_temporal_with_date class Type_handler_datetime_common: public Type_handler_temporal_with_date
{ {
public: public:
virtual ~Type_handler_datetime() {} virtual ~Type_handler_datetime_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
};
class Type_handler_datetime: public Type_handler_datetime_common
{
public:
virtual ~Type_handler_datetime() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
}; };
class Type_handler_datetime2: public Type_handler_temporal_with_date class Type_handler_datetime2: public Type_handler_datetime_common
{ {
public: public:
virtual ~Type_handler_datetime2() {} virtual ~Type_handler_datetime2() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; } enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
}; };
class Type_handler_timestamp: public Type_handler_temporal_with_date class Type_handler_timestamp_common: public Type_handler_temporal_with_date
{ {
public: public:
virtual ~Type_handler_timestamp() {} virtual ~Type_handler_timestamp_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
};
class Type_handler_timestamp: public Type_handler_timestamp_common
{
public:
virtual ~Type_handler_timestamp() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
}; };
class Type_handler_timestamp2: public Type_handler_temporal_with_date class Type_handler_timestamp2: public Type_handler_timestamp_common
{ {
public: public:
virtual ~Type_handler_timestamp2() {} virtual ~Type_handler_timestamp2() {}
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment