summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2015-10-08 08:59:58 +0400
committerAlexander Barkov <bar@mariadb.org>2015-10-08 08:59:58 +0400
commitde1a48e7d914c58cf01b5bda10fea21ea3ec4e28 (patch)
treedabf21513ff3ccb807b7de5940bf684fabbb0ba0
parent87777249017b691ac9a114ae134afa7bbf8d8591 (diff)
downloadmariadb-git-de1a48e7d914c58cf01b5bda10fea21ea3ec4e28.tar.gz
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.
-rw-r--r--sql/item_func.h91
1 files changed, 53 insertions, 38 deletions
diff --git a/sql/item_func.h b/sql/item_func.h
index 921063f8809..d524e62c374 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -383,33 +383,65 @@ public:
};
-class Item_func_hybrid_field_type: public Item_func,
- public Type_handler_hybrid_field_type
+/**
+ Functions whose returned field type is determined at fix_fields() time.
+*/
+class Item_hybrid_func: public Item_func,
+ public Type_handler_hybrid_field_type
+{
+public:
+ 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 *b): Item_func(thd, a, b) { }
+ Item_hybrid_func(THD *thd, Item *a, Item *b, Item *c):
+ Item_func(thd, a, b, c) { }
+ Item_hybrid_func(THD *thd, List<Item> &list): Item_func(thd, list) { }
+ Item_hybrid_func(THD *thd, Item_hybrid_func *item)
+ :Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
+ enum_field_types field_type() const
+ { return Type_handler_hybrid_field_type::field_type(); }
+ enum Item_result result_type () const
+ { return Type_handler_hybrid_field_type::result_type(); }
+ enum Item_result cmp_type () const
+ { return Type_handler_hybrid_field_type::cmp_type(); }
+};
+
+
+/**
+ Functions that at fix_fields() time determine the returned field type,
+ trying to preserve the exact data type of the arguments.
+
+ The descendants have to implement "native" value methods,
+ i.e. str_op(), date_op(), int_op(), real_op(), decimal_op().
+ fix_fields() chooses which of the above value methods will be
+ used during execution time, according to the returned field type.
+
+ For example, if fix_fields() determines that the returned value type
+ is MYSQL_TYPE_LONG, then:
+ - int_op() is chosen as the execution time native method.
+ - val_int() returns the result of int_op() as is.
+ - all other methods, i.e. val_real(), val_decimal(), val_str(), get_date(),
+ call int_op() first, then convert the result to the requested data type.
+*/
+class Item_func_hybrid_field_type: public Item_hybrid_func
{
public:
Item_func_hybrid_field_type(THD *thd):
- Item_func(thd)
+ Item_hybrid_func(thd)
{ collation.set_numeric(); }
Item_func_hybrid_field_type(THD *thd, Item *a):
- Item_func(thd, a)
+ Item_hybrid_func(thd, a)
{ collation.set_numeric(); }
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b):
- Item_func(thd, a, b)
+ Item_hybrid_func(thd, a, b)
{ collation.set_numeric(); }
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b, Item *c):
- Item_func(thd, a, b, c)
+ Item_hybrid_func(thd, a, b, c)
{ collation.set_numeric(); }
Item_func_hybrid_field_type(THD *thd, List<Item> &list):
- Item_func(thd, list)
+ Item_hybrid_func(thd, list)
{ collation.set_numeric(); }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
-
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
@@ -1007,15 +1039,14 @@ public:
than strings.
Perhaps this should be changed eventually (see MDEV-5893).
*/
-class Item_func_min_max :public Item_func,
- public Type_handler_hybrid_field_type
+class Item_func_min_max :public Item_hybrid_func
{
String tmp_value;
int cmp_sign;
THD *thd;
public:
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
- Item_func(thd, list), cmp_sign(cmp_sign_arg)
+ Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
{}
double val_real();
longlong val_int();
@@ -1023,12 +1054,6 @@ public:
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void fix_length_and_dec();
- enum Item_result cmp_type() const
- { return Type_handler_hybrid_field_type::cmp_type(); }
- enum Item_result result_type() const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
};
class Item_func_min :public Item_func_min_max
@@ -1628,29 +1653,19 @@ class user_var_entry;
/**
A class to set and get user variables
*/
-class Item_func_user_var :public Item_func,
- public Type_handler_hybrid_field_type
+class Item_func_user_var :public Item_hybrid_func
{
protected:
user_var_entry *m_var_entry;
public:
LEX_STRING name; // keep it public
Item_func_user_var(THD *thd, LEX_STRING a)
- :Item_func(thd), m_var_entry(NULL), name(a) { }
+ :Item_hybrid_func(thd), m_var_entry(NULL), name(a) { }
Item_func_user_var(THD *thd, LEX_STRING a, Item *b)
- :Item_func(thd, b), m_var_entry(NULL), name(a) { }
+ :Item_hybrid_func(thd, b), m_var_entry(NULL), name(a) { }
Item_func_user_var(THD *thd, Item_func_user_var *item)
- :Item_func(thd, item),
- m_var_entry(item->m_var_entry), name(item->name)
- {
- set_handler_by_result_type(item->result_type());
- }
- enum Item_result cmp_type() const
- { return Type_handler_hybrid_field_type::cmp_type(); }
- enum Item_result result_type() const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
+ :Item_hybrid_func(thd, item),
+ m_var_entry(item->m_var_entry), name(item->name) { }
bool check_vcol_func_processor(uchar *int_arg) { return true; }
};