1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods in Type_handler + MDEV-12497 + MDEV-12504

This patch does the following:

1. Adds a new method Type_handler_hybrid_field_type::aggregate_for_min_max()

   - For non-traditional data types it uses
     type_handler_data->m_type_aggregator_for_result.find_handler()
     This allows pluggable data types to define in the future their
     own behavior of the result data type detection for LEAST/GREATEST.
     Also, this disallows expressions of the GEOMETRY data type
     (and its variants such as POINT) to be mixed in with
     numeric and temporal data types in LEAST/GREATEST.

   - For traditional data types it reproduces the old behavior of
     the result data type detection (but not attributes, see below).

2. Adds a new virtual method Type_handler::Item_func_min_max_fix_attributes()
   and reuses as much as possible the code that calculates data type attributes
   for CASE-alike functions (e.g. CASE..THEN, COALESCE, IF).

   As the old code responsible for attributes calculation in the old
   implementation of Item_func_min_max::fix_length_and_dec()
   was not fully correct, this automatically fixes the following bugs:

   - MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
     The old fix_length_and_dec() calculated max_length before
     character set aggregation. Now max_length is calculated after, in
     Item_func::count_string_length() called from
     Item_func::aggregate_attributes_string() called from
     Type_handler_string_result::Item_hybrid_func_fix_attributes() called from
     Type_handler::Item_func_min_max_fix_attributes() called from
     Item_func_min_max::fix_length_and_dec().

   - MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
     The old fix_length_and_dec() simply used the maximum of max_length
     among all arguments to set its own max_length and did not take
     into account that a mixture of DATE and TIME becomes DATETIME.
     Now this is correctly handled by:
     Type_handler_datetime_common::Item_hybrid_func_fix_attributes() called from
     Type_handler::Item_func_min_max_fix_attributes() called from
     Item_func_min_max::fix_length_and_dec().

3. Removes the old implementation of Item_func_min_max::fix_length_and_dec()
   and replaces it to calls of the new methods.

4. Cleanup: moves the code related to unsigned_flag processing
   from Type_handler_hybrid_field_type::aggregate_for_result()
   to   Type_handler_int_result::Item_hybrid_func_fix_attributes().
   This is done:
   - to avoid code duplication in
     Type_handler_hybrid_field_type::aggregate_for_min_max()
   - to get rid of one more call for field_type(), which is unfriendly
     to the conceipt of pluggable data types.
This commit is contained in:
Alexander Barkov
2017-04-22 23:47:27 +04:00
parent ba670edfa3
commit 658082551f
14 changed files with 575 additions and 157 deletions

View File

@@ -485,6 +485,10 @@ public:
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items,
uint nitems) const= 0;
virtual bool Item_func_min_max_fix_attributes(THD *thd,
Item_func_min_max *func,
Item **items,
uint nitems) const;
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0;
virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0;
@@ -840,6 +844,8 @@ public:
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_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
@@ -1602,6 +1608,7 @@ public:
class Type_handler_hybrid_field_type
{
const Type_handler *m_type_handler;
bool aggregate_for_min_max(const Type_handler *other);
public:
Type_handler_hybrid_field_type();
Type_handler_hybrid_field_type(const Type_handler *handler)
@@ -1657,6 +1664,8 @@ public:
bool aggregate_for_result(const Type_handler *other);
bool aggregate_for_result(const char *funcname,
Item **item, uint nitems, bool treat_bit_as_number);
bool aggregate_for_min_max(const char *funcname, Item **item, uint nitems);
bool aggregate_for_num_op(const class Type_aggregator *aggregator,
const Type_handler *h0, const Type_handler *h1);
};