Skip to content

Commit de1a48e

Browse files
author
Alexander Barkov
committed
A clean-up for a few recent result set metadata related bug fixes:
- MDEV-8875 Wrong metadata for MAX(CAST(time_column AS DATETIME)) - MDEV-8873 Wrong field type or metadata for LEAST(int_column,string_column) - MDEV-8912 Wrong metadata or type for @c:=string_or_blob_field Adding Item_hybrid_func as a common parent for Item_func_hybrid_field_type, Item_func_min_max, Item_func_user_var. This removes some duplicate code.
1 parent 8777724 commit de1a48e

File tree

1 file changed

+53
-38
lines changed

1 file changed

+53
-38
lines changed

sql/item_func.h

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -383,33 +383,65 @@ class Item_real_func :public Item_func
383383
};
384384

385385

386-
class Item_func_hybrid_field_type: public Item_func,
387-
public Type_handler_hybrid_field_type
386+
/**
387+
Functions whose returned field type is determined at fix_fields() time.
388+
*/
389+
class Item_hybrid_func: public Item_func,
390+
public Type_handler_hybrid_field_type
391+
{
392+
public:
393+
Item_hybrid_func(THD *thd): Item_func(thd) { }
394+
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
395+
Item_hybrid_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { }
396+
Item_hybrid_func(THD *thd, Item *a, Item *b, Item *c):
397+
Item_func(thd, a, b, c) { }
398+
Item_hybrid_func(THD *thd, List<Item> &list): Item_func(thd, list) { }
399+
Item_hybrid_func(THD *thd, Item_hybrid_func *item)
400+
:Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
401+
enum_field_types field_type() const
402+
{ return Type_handler_hybrid_field_type::field_type(); }
403+
enum Item_result result_type () const
404+
{ return Type_handler_hybrid_field_type::result_type(); }
405+
enum Item_result cmp_type () const
406+
{ return Type_handler_hybrid_field_type::cmp_type(); }
407+
};
408+
409+
410+
/**
411+
Functions that at fix_fields() time determine the returned field type,
412+
trying to preserve the exact data type of the arguments.
413+
414+
The descendants have to implement "native" value methods,
415+
i.e. str_op(), date_op(), int_op(), real_op(), decimal_op().
416+
fix_fields() chooses which of the above value methods will be
417+
used during execution time, according to the returned field type.
418+
419+
For example, if fix_fields() determines that the returned value type
420+
is MYSQL_TYPE_LONG, then:
421+
- int_op() is chosen as the execution time native method.
422+
- val_int() returns the result of int_op() as is.
423+
- all other methods, i.e. val_real(), val_decimal(), val_str(), get_date(),
424+
call int_op() first, then convert the result to the requested data type.
425+
*/
426+
class Item_func_hybrid_field_type: public Item_hybrid_func
388427
{
389428
public:
390429
Item_func_hybrid_field_type(THD *thd):
391-
Item_func(thd)
430+
Item_hybrid_func(thd)
392431
{ collation.set_numeric(); }
393432
Item_func_hybrid_field_type(THD *thd, Item *a):
394-
Item_func(thd, a)
433+
Item_hybrid_func(thd, a)
395434
{ collation.set_numeric(); }
396435
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b):
397-
Item_func(thd, a, b)
436+
Item_hybrid_func(thd, a, b)
398437
{ collation.set_numeric(); }
399438
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b, Item *c):
400-
Item_func(thd, a, b, c)
439+
Item_hybrid_func(thd, a, b, c)
401440
{ collation.set_numeric(); }
402441
Item_func_hybrid_field_type(THD *thd, List<Item> &list):
403-
Item_func(thd, list)
442+
Item_hybrid_func(thd, list)
404443
{ collation.set_numeric(); }
405444

406-
enum_field_types field_type() const
407-
{ return Type_handler_hybrid_field_type::field_type(); }
408-
enum Item_result result_type () const
409-
{ return Type_handler_hybrid_field_type::result_type(); }
410-
enum Item_result cmp_type () const
411-
{ return Type_handler_hybrid_field_type::cmp_type(); }
412-
413445
double val_real();
414446
longlong val_int();
415447
my_decimal *val_decimal(my_decimal *);
@@ -1007,28 +1039,21 @@ class Item_func_units :public Item_real_func
10071039
than strings.
10081040
Perhaps this should be changed eventually (see MDEV-5893).
10091041
*/
1010-
class Item_func_min_max :public Item_func,
1011-
public Type_handler_hybrid_field_type
1042+
class Item_func_min_max :public Item_hybrid_func
10121043
{
10131044
String tmp_value;
10141045
int cmp_sign;
10151046
THD *thd;
10161047
public:
10171048
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
1018-
Item_func(thd, list), cmp_sign(cmp_sign_arg)
1049+
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
10191050
{}
10201051
double val_real();
10211052
longlong val_int();
10221053
String *val_str(String *);
10231054
my_decimal *val_decimal(my_decimal *);
10241055
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
10251056
void fix_length_and_dec();
1026-
enum Item_result cmp_type() const
1027-
{ return Type_handler_hybrid_field_type::cmp_type(); }
1028-
enum Item_result result_type() const
1029-
{ return Type_handler_hybrid_field_type::result_type(); }
1030-
enum_field_types field_type() const
1031-
{ return Type_handler_hybrid_field_type::field_type(); }
10321057
};
10331058

10341059
class Item_func_min :public Item_func_min_max
@@ -1628,29 +1653,19 @@ class user_var_entry;
16281653
/**
16291654
A class to set and get user variables
16301655
*/
1631-
class Item_func_user_var :public Item_func,
1632-
public Type_handler_hybrid_field_type
1656+
class Item_func_user_var :public Item_hybrid_func
16331657
{
16341658
protected:
16351659
user_var_entry *m_var_entry;
16361660
public:
16371661
LEX_STRING name; // keep it public
16381662
Item_func_user_var(THD *thd, LEX_STRING a)
1639-
:Item_func(thd), m_var_entry(NULL), name(a) { }
1663+
:Item_hybrid_func(thd), m_var_entry(NULL), name(a) { }
16401664
Item_func_user_var(THD *thd, LEX_STRING a, Item *b)
1641-
:Item_func(thd, b), m_var_entry(NULL), name(a) { }
1665+
:Item_hybrid_func(thd, b), m_var_entry(NULL), name(a) { }
16421666
Item_func_user_var(THD *thd, Item_func_user_var *item)
1643-
:Item_func(thd, item),
1644-
m_var_entry(item->m_var_entry), name(item->name)
1645-
{
1646-
set_handler_by_result_type(item->result_type());
1647-
}
1648-
enum Item_result cmp_type() const
1649-
{ return Type_handler_hybrid_field_type::cmp_type(); }
1650-
enum Item_result result_type() const
1651-
{ return Type_handler_hybrid_field_type::result_type(); }
1652-
enum_field_types field_type() const
1653-
{ return Type_handler_hybrid_field_type::field_type(); }
1667+
:Item_hybrid_func(thd, item),
1668+
m_var_entry(item->m_var_entry), name(item->name) { }
16541669
bool check_vcol_func_processor(uchar *int_arg) { return true; }
16551670
};
16561671

0 commit comments

Comments
 (0)