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()
set_handler_by_field_type(agg_field_type(agg, nagg, true));
if (Item_func_case::result_type() == STRING_RESULT)
{
if (count_string_result_length(Item_func_case::field_type(), agg, nagg))
if (fix_attributes(agg, nagg))
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.
*/
for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
......@@ -3121,11 +3120,6 @@ void Item_func_case::fix_length_and_dec()
if (else_expr_num != -1)
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
......@@ -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()) {
case STRING_RESULT:
if (count_string_result_length(Item_hybrid_func::field_type(),
items, nitems))
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);
}
bool rc= Item_hybrid_func::type_handler()->
Item_hybrid_func_fix_attributes(current_thd, this, items, nitems);
DBUG_ASSERT(!rc || current_thd->is_error());
return rc;
}
/****************************************************************************
......
......@@ -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
result length/precision depends on argument ones.
......@@ -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 items Argument array.
......@@ -673,18 +649,13 @@ void Item_func::count_real_length(Item **items, uint nitems)
@retval False on success, true on error.
*/
bool Item_func::count_string_result_length(enum_field_types field_type_arg,
Item **items, uint nitems)
bool Item_func::count_string_length(Item **items, uint nitems)
{
DBUG_ASSERT(!is_temporal_type(field_type()));
if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
return true;
if (is_temporal_type(field_type_arg))
count_datetime_length(field_type_arg, items, nitems);
else
{
count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0;
}
return false;
}
......
......@@ -45,11 +45,49 @@ class Item_func :public Item_func_or_sum
void count_only_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems);
void count_datetime_length(enum_field_types field_type,
Item **item, uint nitems);
bool count_string_result_length(enum_field_types field_type,
Item **item, uint nitems);
bool count_string_length(Item **item, uint nitems);
uint count_max_decimals(Item **item, uint nitems)
{
uint res= 0;
for (uint i= 0; i < nitems; i++)
set_if_bigger(res, item[i]->decimals);
return res;
}
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;
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,
public Type_handler_hybrid_field_type
{
protected:
void fix_attributes(Item **item, uint nitems);
bool fix_attributes(Item **item, uint nitems);
public:
Item_hybrid_func(THD *thd): Item_func(thd) { }
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
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;
class Item_cache;
class Item_sum_hybrid;
class Item_func_hex;
class Item_hybrid_func;
class Item_func_hybrid_field_type;
class Item_func_between;
class Item_func_in;
......@@ -298,6 +299,9 @@ class Type_handler
bool no_conversions) 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 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 String *Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const= 0;
......@@ -391,6 +395,12 @@ class Type_handler_row: public Type_handler
}
Item_cache *Item_get_cache(THD *thd, const Item *item) 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
{
DBUG_ASSERT(0);
......@@ -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;
Item_cache *Item_get_cache(THD *thd, const Item *item) 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;
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 *,
......@@ -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;
Item_cache *Item_get_cache(THD *thd, const Item *item) 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;
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 *,
......@@ -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;
Item_cache *Item_get_cache(THD *thd, const Item *item) 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;
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 *,
......@@ -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;
Item_cache *Item_get_cache(THD *thd, const Item *item) 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;
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 *,
......@@ -778,6 +796,8 @@ class Type_handler_time_common: public Type_handler_temporal_result
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const Type_handler *type_handler_for_comparison() 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;
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
};
class Type_handler_date: public Type_handler_temporal_with_date
class Type_handler_date_common: public Type_handler_temporal_with_date
{
public:
virtual ~Type_handler_date() {}
virtual ~Type_handler_date_common() {}
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,
const Field *target) const;
};
class Type_handler_newdate: public Type_handler_temporal_with_date
class Type_handler_newdate: public Type_handler_date_common
{
public:
virtual ~Type_handler_newdate() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *make_conversion_table_field(TABLE *, uint metadata,
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:
virtual ~Type_handler_datetime() {}
virtual ~Type_handler_datetime_common() {}
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,
const Field *target) const;
};
class Type_handler_datetime2: public Type_handler_temporal_with_date
class Type_handler_datetime2: public Type_handler_datetime_common
{
public:
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; }
Field *make_conversion_table_field(TABLE *, uint metadata,
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:
virtual ~Type_handler_timestamp() {}
virtual ~Type_handler_timestamp_common() {}
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,
const Field *target) const;
};
class Type_handler_timestamp2: public Type_handler_temporal_with_date
class Type_handler_timestamp2: public Type_handler_timestamp_common
{
public:
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; }
Field *make_conversion_table_field(TABLE *, uint metadata,
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