Commit cd828fb9 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9215 Detect cmp_type() and result_type() from field_type()

Part4: Deriving Item_temporal_hybrid_func from Type_handler_hybrid_field_type
parent 47a8c6c3
...@@ -1558,9 +1558,9 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str) ...@@ -1558,9 +1558,9 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str)
return (String *) 0; return (String *) 0;
/* Check that the returned timestamp type matches to the function type */ /* Check that the returned timestamp type matches to the function type */
DBUG_ASSERT(cached_field_type == MYSQL_TYPE_STRING || DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE || ltime.time_type == MYSQL_TIMESTAMP_NONE ||
mysql_type_to_time_type(cached_field_type) == ltime.time_type); mysql_type_to_time_type(field_type()) == ltime.time_type);
return str; return str;
} }
...@@ -2081,7 +2081,7 @@ void Item_date_add_interval::fix_length_and_dec() ...@@ -2081,7 +2081,7 @@ void Item_date_add_interval::fix_length_and_dec()
(This is because you can't know if the string contains a DATE, (This is because you can't know if the string contains a DATE,
MYSQL_TIME or DATETIME argument) MYSQL_TIME or DATETIME argument)
*/ */
cached_field_type= MYSQL_TYPE_STRING; set_handler_by_field_type(MYSQL_TYPE_STRING);
arg0_field_type= args[0]->field_type(); arg0_field_type= args[0]->field_type();
uint interval_dec= 0; uint interval_dec= 0;
if (int_type == INTERVAL_MICROSECOND || if (int_type == INTERVAL_MICROSECOND ||
...@@ -2095,25 +2095,25 @@ void Item_date_add_interval::fix_length_and_dec() ...@@ -2095,25 +2095,25 @@ void Item_date_add_interval::fix_length_and_dec()
arg0_field_type == MYSQL_TYPE_TIMESTAMP) arg0_field_type == MYSQL_TYPE_TIMESTAMP)
{ {
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec); decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
} }
else if (arg0_field_type == MYSQL_TYPE_DATE) else if (arg0_field_type == MYSQL_TYPE_DATE)
{ {
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH) if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
cached_field_type= arg0_field_type; set_handler_by_field_type(arg0_field_type);
else else
{ {
decimals= interval_dec; decimals= interval_dec;
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
} }
} }
else if (arg0_field_type == MYSQL_TYPE_TIME) else if (arg0_field_type == MYSQL_TYPE_TIME)
{ {
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec); decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH) if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
cached_field_type= arg0_field_type; set_handler_by_field_type(arg0_field_type);
else else
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
} }
else else
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec); decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
...@@ -2126,7 +2126,7 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ...@@ -2126,7 +2126,7 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
INTERVAL interval; INTERVAL interval;
if (args[0]->get_date(ltime, if (args[0]->get_date(ltime,
cached_field_type == MYSQL_TYPE_TIME ? field_type() == MYSQL_TYPE_TIME ?
TIME_TIME_ONLY : 0) || TIME_TIME_ONLY : 0) ||
get_interval_value(args[1], int_type, &interval)) get_interval_value(args[1], int_type, &interval))
return (null_value=1); return (null_value=1);
...@@ -2630,20 +2630,20 @@ void Item_func_add_time::fix_length_and_dec() ...@@ -2630,20 +2630,20 @@ void Item_func_add_time::fix_length_and_dec()
- Otherwise the result is MYSQL_TYPE_STRING - Otherwise the result is MYSQL_TYPE_STRING
*/ */
cached_field_type= MYSQL_TYPE_STRING; set_handler_by_field_type(MYSQL_TYPE_STRING);
arg0_field_type= args[0]->field_type(); arg0_field_type= args[0]->field_type();
if (arg0_field_type == MYSQL_TYPE_DATE || if (arg0_field_type == MYSQL_TYPE_DATE ||
arg0_field_type == MYSQL_TYPE_DATETIME || arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP || arg0_field_type == MYSQL_TYPE_TIMESTAMP ||
is_date) is_date)
{ {
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
args[1]->temporal_precision(MYSQL_TYPE_TIME)); args[1]->temporal_precision(MYSQL_TYPE_TIME));
} }
else if (arg0_field_type == MYSQL_TYPE_TIME) else if (arg0_field_type == MYSQL_TYPE_TIME)
{ {
cached_field_type= MYSQL_TYPE_TIME; set_handler_by_field_type(MYSQL_TYPE_TIME);
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
args[1]->temporal_precision(MYSQL_TYPE_TIME)); args[1]->temporal_precision(MYSQL_TYPE_TIME));
} }
...@@ -2669,7 +2669,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ...@@ -2669,7 +2669,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
longlong seconds; longlong seconds;
int l_sign= sign; int l_sign= sign;
if (cached_field_type == MYSQL_TYPE_DATETIME) if (Item_func_add_time::field_type() == MYSQL_TYPE_DATETIME)
{ {
// TIMESTAMP function OR the first argument is DATE/DATETIME/TIMESTAMP // TIMESTAMP function OR the first argument is DATE/DATETIME/TIMESTAMP
if (get_arg0_date(&l_time1, 0) || if (get_arg0_date(&l_time1, 0) ||
...@@ -3149,7 +3149,7 @@ void Item_func_str_to_date::fix_length_and_dec() ...@@ -3149,7 +3149,7 @@ void Item_func_str_to_date::fix_length_and_dec()
#endif #endif
} }
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
decimals= TIME_SECOND_PART_DIGITS; decimals= TIME_SECOND_PART_DIGITS;
if ((const_item= args[1]->const_item())) if ((const_item= args[1]->const_item()))
{ {
...@@ -3164,24 +3164,24 @@ void Item_func_str_to_date::fix_length_and_dec() ...@@ -3164,24 +3164,24 @@ void Item_func_str_to_date::fix_length_and_dec()
get_date_time_result_type(format->ptr(), format->length()); get_date_time_result_type(format->ptr(), format->length());
switch (cached_format_type) { switch (cached_format_type) {
case DATE_ONLY: case DATE_ONLY:
cached_field_type= MYSQL_TYPE_DATE; set_handler_by_field_type(MYSQL_TYPE_DATE);
break; break;
case TIME_MICROSECOND: case TIME_MICROSECOND:
decimals= 6; decimals= 6;
/* fall through */ /* fall through */
case TIME_ONLY: case TIME_ONLY:
cached_field_type= MYSQL_TYPE_TIME; set_handler_by_field_type(MYSQL_TYPE_TIME);
break; break;
case DATE_TIME_MICROSECOND: case DATE_TIME_MICROSECOND:
decimals= 6; decimals= 6;
/* fall through */ /* fall through */
case DATE_TIME: case DATE_TIME:
cached_field_type= MYSQL_TYPE_DATETIME; set_handler_by_field_type(MYSQL_TYPE_DATETIME);
break; break;
} }
} }
} }
cached_timestamp_type= mysql_type_to_time_type(cached_field_type); cached_timestamp_type= mysql_type_to_time_type(field_type());
Item_temporal_func::fix_length_and_dec(); Item_temporal_func::fix_length_and_dec();
} }
......
...@@ -495,7 +495,6 @@ public: ...@@ -495,7 +495,6 @@ public:
Item_temporal_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} Item_temporal_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {}
Item_temporal_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) {} Item_temporal_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) {}
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Item_result cmp_type() const { return TIME_RESULT; } Item_result cmp_type() const { return TIME_RESULT; }
String *val_str(String *str); String *val_str(String *str);
longlong val_int() { return val_int_from_date(); } longlong val_int() { return val_int_from_date(); }
...@@ -515,20 +514,20 @@ public: ...@@ -515,20 +514,20 @@ public:
Abstract class for functions returning TIME, DATE, DATETIME or string values, Abstract class for functions returning TIME, DATE, DATETIME or string values,
whose data type depends on parameters and is set at fix_fields time. whose data type depends on parameters and is set at fix_fields time.
*/ */
class Item_temporal_hybrid_func: public Item_temporal_func class Item_temporal_hybrid_func: public Item_temporal_func,
public Type_handler_hybrid_field_type
{ {
protected: protected:
enum_field_types cached_field_type; // TIME, DATE, DATETIME or STRING
String ascii_buf; // Conversion buffer String ascii_buf; // Conversion buffer
public: public:
Item_temporal_hybrid_func(THD *thd, Item *a, Item *b): Item_temporal_hybrid_func(THD *thd, Item *a, Item *b):
Item_temporal_func(thd, a, b) {} Item_temporal_func(thd, a, b) {}
enum_field_types field_type() const { return cached_field_type; } enum_field_types field_type() const
Item_result cmp_type() const { return Type_handler_hybrid_field_type::field_type(); }
{ enum Item_result result_type () const
return cached_field_type == MYSQL_TYPE_STRING ? { return Type_handler_hybrid_field_type::result_type(); }
STRING_RESULT : TIME_RESULT; enum Item_result cmp_type () const
} { return Type_handler_hybrid_field_type::cmp_type(); }
CHARSET_INFO *charset_for_protocol() const CHARSET_INFO *charset_for_protocol() const
{ {
/* /*
...@@ -538,7 +537,7 @@ public: ...@@ -538,7 +537,7 @@ public:
(which is fixed from @@collation_connection in fix_length_and_dec). (which is fixed from @@collation_connection in fix_length_and_dec).
*/ */
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
return cached_field_type == MYSQL_TYPE_STRING ? return Item_temporal_hybrid_func::field_type() == MYSQL_TYPE_STRING ?
collation.collation : &my_charset_bin; collation.collation : &my_charset_bin;
} }
/** /**
...@@ -581,6 +580,17 @@ public: ...@@ -581,6 +580,17 @@ public:
}; };
class Item_datetimefunc :public Item_temporal_func
{
public:
Item_datetimefunc(THD *thd): Item_temporal_func(thd) {}
Item_datetimefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {}
Item_datetimefunc(THD *thd, Item *a, Item *b, Item *c):
Item_temporal_func(thd, a, b ,c) {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
};
/* Abstract CURTIME function. Children should define what time zone is used */ /* Abstract CURTIME function. Children should define what time zone is used */
class Item_func_curtime :public Item_timefunc class Item_func_curtime :public Item_timefunc
...@@ -665,11 +675,11 @@ public: ...@@ -665,11 +675,11 @@ public:
/* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */ /* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */
class Item_func_now :public Item_temporal_func class Item_func_now :public Item_datetimefunc
{ {
MYSQL_TIME ltime; MYSQL_TIME ltime;
public: public:
Item_func_now(THD *thd, uint dec): Item_temporal_func(thd) { decimals= dec; } Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd) { decimals= dec; }
bool fix_fields(THD *, Item **); bool fix_fields(THD *, Item **);
void fix_length_and_dec() void fix_length_and_dec()
{ {
...@@ -759,11 +769,11 @@ public: ...@@ -759,11 +769,11 @@ public:
}; };
class Item_func_from_unixtime :public Item_temporal_func class Item_func_from_unixtime :public Item_datetimefunc
{ {
Time_zone *tz; Time_zone *tz;
public: public:
Item_func_from_unixtime(THD *thd, Item *a): Item_temporal_func(thd, a) {} Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
const char *func_name() const { return "from_unixtime"; } const char *func_name() const { return "from_unixtime"; }
void fix_length_and_dec(); void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
...@@ -784,7 +794,7 @@ class Time_zone; ...@@ -784,7 +794,7 @@ class Time_zone;
tables can be used during this function calculation for loading time zone tables can be used during this function calculation for loading time zone
descriptions. descriptions.
*/ */
class Item_func_convert_tz :public Item_temporal_func class Item_func_convert_tz :public Item_datetimefunc
{ {
/* /*
If time zone parameters are constants we are caching objects that If time zone parameters are constants we are caching objects that
...@@ -796,7 +806,7 @@ class Item_func_convert_tz :public Item_temporal_func ...@@ -796,7 +806,7 @@ class Item_func_convert_tz :public Item_temporal_func
Time_zone *from_tz, *to_tz; Time_zone *from_tz, *to_tz;
public: public:
Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c): Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c):
Item_temporal_func(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {} Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {}
const char *func_name() const { return "convert_tz"; } const char *func_name() const { return "convert_tz"; }
void fix_length_and_dec(); void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
......
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