Details
-
Task
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
None
Description
These methods:
Item_date_add_interval::get_date()
|
Item_func_add_time::get_date()
|
have tests for field_type(). This is not friendly to new data types, which might want to have these functions in addition to the currently supported data types DATETIME, DATE, TIME.
Near future candidates:
- TIMESTAMP: Soon we'll change the temporal arithmetic to preserve the MYSQL_TYPE_TIMESTAMP type (MDEV-15750).
- TIMESTAMP WITH TIME ZONE
Also, we'll introduce INTERVAL data types natively and it will be possible to use intervals outside of the temporal arithmetic context, e.g.:
CREATE TABLE t1 (a INTERVAL HOUR TO SECOND); |
INSERT INTO t1 VALUES (INTERVAL '10:20:30' HOUR TO SECOND); |
SELECT * FROM t1 WHERE COALESCE(a, INTERVAL '00:00:00' HOUR TO SECOND) = INTERVAL '10:00:00' HOUR TO SECOND; |
So, these syntax tricks:
| bit_expr '+' INTERVAL_SYM expr interval %prec '+' |
{
|
$$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 0); |
if (unlikely($$ == NULL)) |
MYSQL_YYABORT;
|
}
|
| DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' |
{
|
$$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0); |
if (unlikely($$ == NULL)) |
MYSQL_YYABORT;
|
}
|
will disappear soon. The syntax for interval expressions will migrate to the rule simple_expr. Expressions starting with the INTERVAL keyword will become normal expressions with they own Type_handler.
To make it possible for new data types to add their own implementations for ADDTIME()/SUBTIME(), DATE_ADD(), DATE_SUB(), as well as for the operators + and -, we'll do the following:
- Introduce a new class Item_handled_func, with approximately this prototype:
class Item_handled_func: public Item_func
{
public:
class Handler
{
public:
virtual ~Handler() { }
virtual String *val_str(Item_handled_func *, String *) const= 0;
virtual String *val_str_ascii(Item_handled_func *, String *) const= 0;
virtual double val_real(Item_handled_func *) const= 0;
virtual longlong val_int(Item_handled_func *) const= 0;
virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0;
virtual bool get_date(Item_handled_func *, MYSQL_TIME *, ulonglong fuzzydate) const= 0;
virtual const Type_handler *return_type_handler() const= 0;
virtual bool fix_length_and_dec(Item_handled_func *) const= 0;
};
protected:
const Handler *m_func_handler;
public:
Item_handled_func(THD *thd, Item *a)
:Item_func(thd, a), m_func_handler(NULL) { }
Item_handled_func(THD *thd, Item *a, Item *b)
:Item_func(thd, a, b), m_func_handler(NULL) { }
void set_func_handler(const Handler *handler)
{
m_func_handler= handler;
}
const Type_handler *type_handler() const
{
return m_func_handler->return_type_handler();
}
String *val_str(String *to)
{
return m_func_handler->val_str(this, to);
}
String *val_str_ascii(String *to)
{
return m_func_handler->val_str_ascii(this, to);
}
double val_real()
{
return m_func_handler->val_real(this);
}
longlong val_int()
{
return m_func_handler->val_int(this);
}
my_decimal *val_decimal(my_decimal *to)
{
return m_func_handler->val_decimal(this, to);
}
bool get_date(MYSQL_TIME *to, ulonglong fuzzydate)
{
return m_func_handler->get_date(this, to, fuzzydate);
}
};
- Change Item_func_add_time, Item_date_add_interval, Item_func_str_to_date to derive from the new class Item_handled_func.
- Remove class Item_temporal_hybrid_func
- Add handler classes for the former Item_temporal_hybrid_func descendants:
Item_handled_func::Handler
Func_handler_temporal_hybrid
Func_handler_date_add_interval
Func_handler_date_add_interval_datetime
Func_handler_date_add_interval_date
Func_handler_date_add_interval_time
Func_handler_date_add_interval_string
Func_handler_add_time
Func_handler_add_time_datetime
Func_handler_add_time_time
Func_handler_add_time_string
Func_handler_str_to_date_datetime
Func_handler_str_to_date_datetime_sec
Func_handler_str_to_date_datetime_usec
Func_handler_str_to_date_date
Func_handler_str_to_date_time
Func_handler_str_to_date_time_sec
Func_handler_str_to_date_time_usec
- Move the code from Item_func_xxx::get_date() and Item_func_xxx::fix_length_and_dec() to the corresponding methods in Func_handler_xxx
After this change:
- All tests for field_type() inside Item_func_xxx::get_date() will be gone
- The block in Item_func_xxx::fix_length_and_dec() which decides the data type and its attributes will be simplified. For example:
bool Item_date_add_interval::fix_length_and_dec()
{
..
arg0_field_type= args[0]->field_type();
Â
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
{
set_func_handler(&func_handler_date_add_interval_datetime);
}
else if (arg0_field_type == MYSQL_TYPE_DATE)
{
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
set_func_handler(&func_handler_date_add_interval_date);
else
set_func_handler(&func_handler_date_add_interval_datetime);
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
set_func_handler(&func_handler_date_add_interval_time);
else
set_func_handler(&func_handler_date_add_interval_datetime_arg0_time);
}
else
{
set_func_handler(&func_handler_date_add_interval_string);
}
maybe_null= true;
return m_func_handler->fix_length_and_dec(this);
}
Notice, the above code does not set attributes directly anymore. Attributes are set by the call for m_func_handler->fix_length_and_dec(this).
Note, after this change, the fix_length_and_dec() part will sill have conditions testing field_type(). This is OK. This main goal of this task is to remove field_type() tests from get_date()! The remaining tests in fix_length_and_dec() will be removed in a separate change, when we add a registry of overloaded functions (in a way similar to how we added Type_aggregator for comparison functions and for CASE and its abbreviations).
Note, this task does not touch Item_func_plus and Item_func_minus. Eventually they'll also be changed to derive from Item_handled_func, in a separate task.
Attachments
Issue Links
- blocks
-
MDEV-4912 Data type plugin API version 1
- Closed
-
MDEV-15750 preserve MYSQL_TYPE_TIMESTAMP in temporal arithmetics
- Stalled