mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-16874 Implement class Item_handled_func
This commit is contained in:
@ -1716,7 +1716,6 @@ min(timestampadd(month, 1>'', from_days('%Z')))
|
|||||||
NULL
|
NULL
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1292 Truncated incorrect INTEGER value: '%Z'
|
Warning 1292 Truncated incorrect INTEGER value: '%Z'
|
||||||
Warning 1292 Truncated incorrect DOUBLE value: ''
|
|
||||||
Warning 1292 Incorrect datetime value: '0000-00-00'
|
Warning 1292 Incorrect datetime value: '0000-00-00'
|
||||||
SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
|
SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
|
||||||
create table t1(a time);
|
create table t1(a time);
|
||||||
|
@ -40,8 +40,6 @@ class Item_func :public Item_func_or_sum,
|
|||||||
{
|
{
|
||||||
void sync_with_sum_func_and_with_field(List<Item> &list);
|
void sync_with_sum_func_and_with_field(List<Item> &list);
|
||||||
protected:
|
protected:
|
||||||
String *val_str_from_val_str_ascii(String *str, String *str2);
|
|
||||||
|
|
||||||
virtual bool check_arguments() const
|
virtual bool check_arguments() const
|
||||||
{
|
{
|
||||||
return check_argument_types_scalar(0, arg_count);
|
return check_argument_types_scalar(0, arg_count);
|
||||||
@ -188,6 +186,8 @@ public:
|
|||||||
update_null_value();
|
update_null_value();
|
||||||
return null_value;
|
return null_value;
|
||||||
}
|
}
|
||||||
|
String *val_str_from_val_str_ascii(String *str, String *str2);
|
||||||
|
|
||||||
void signal_divide_by_null();
|
void signal_divide_by_null();
|
||||||
friend class udf_handler;
|
friend class udf_handler;
|
||||||
Field *create_field_for_create_select(TABLE *table)
|
Field *create_field_for_create_select(TABLE *table)
|
||||||
@ -450,6 +450,64 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Functions that at fix_fields() time determine the returned field type,
|
Functions that at fix_fields() time determine the returned field type,
|
||||||
trying to preserve the exact data type of the arguments.
|
trying to preserve the exact data type of the arguments.
|
||||||
|
@ -58,6 +58,29 @@
|
|||||||
/** Day number for Dec 31st, 9999. */
|
/** Day number for Dec 31st, 9999. */
|
||||||
#define MAX_DAY_NUMBER 3652424L
|
#define MAX_DAY_NUMBER 3652424L
|
||||||
|
|
||||||
|
|
||||||
|
Func_handler_date_add_interval_datetime_arg0_time
|
||||||
|
func_handler_date_add_interval_datetime_arg0_time;
|
||||||
|
|
||||||
|
Func_handler_date_add_interval_datetime func_handler_date_add_interval_datetime;
|
||||||
|
Func_handler_date_add_interval_date func_handler_date_add_interval_date;
|
||||||
|
Func_handler_date_add_interval_time func_handler_date_add_interval_time;
|
||||||
|
Func_handler_date_add_interval_string func_handler_date_add_interval_string;
|
||||||
|
|
||||||
|
Func_handler_add_time_datetime func_handler_add_time_datetime_add(1);
|
||||||
|
Func_handler_add_time_datetime func_handler_add_time_datetime_sub(-1);
|
||||||
|
Func_handler_add_time_time func_handler_add_time_time_add(1);
|
||||||
|
Func_handler_add_time_time func_handler_add_time_time_sub(-1);
|
||||||
|
Func_handler_add_time_string func_handler_add_time_string_add(1);
|
||||||
|
Func_handler_add_time_string func_handler_add_time_string_sub(-1);
|
||||||
|
|
||||||
|
Func_handler_str_to_date_datetime_sec func_handler_str_to_date_datetime_sec;
|
||||||
|
Func_handler_str_to_date_datetime_usec func_handler_str_to_date_datetime_usec;
|
||||||
|
Func_handler_str_to_date_date func_handler_str_to_date_date;
|
||||||
|
Func_handler_str_to_date_time_sec func_handler_str_to_date_time_sec;
|
||||||
|
Func_handler_str_to_date_time_usec func_handler_str_to_date_time_usec;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Date formats corresponding to compound %r and %T conversion specifiers
|
Date formats corresponding to compound %r and %T conversion specifiers
|
||||||
|
|
||||||
@ -1482,19 +1505,20 @@ String *Item_temporal_func::val_str(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String *Item_temporal_hybrid_func::val_str_ascii(String *str)
|
String *Func_handler_temporal_hybrid::val_str_ascii(Item_handled_func *item,
|
||||||
|
String *str) const
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(item->is_fixed());
|
||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
|
|
||||||
if (get_date(<ime, 0) ||
|
if (get_date(item, <ime, 0) ||
|
||||||
(null_value= my_TIME_to_str(<ime, str, decimals)))
|
(item->null_value= my_TIME_to_str(<ime, str, item->decimals)))
|
||||||
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(field_type() == MYSQL_TYPE_STRING ||
|
DBUG_ASSERT(item->field_type() == MYSQL_TYPE_STRING ||
|
||||||
ltime.time_type == MYSQL_TIMESTAMP_NONE ||
|
ltime.time_type == MYSQL_TIMESTAMP_NONE ||
|
||||||
ltime.time_type == mysql_timestamp_type());
|
ltime.time_type == return_type_handler()->mysql_timestamp_type());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2088,115 +2112,44 @@ bool Item_date_add_interval::fix_length_and_dec()
|
|||||||
MYSQL_TIME or DATETIME argument)
|
MYSQL_TIME or DATETIME argument)
|
||||||
*/
|
*/
|
||||||
arg0_field_type= args[0]->field_type();
|
arg0_field_type= args[0]->field_type();
|
||||||
uint interval_dec= 0;
|
|
||||||
if (int_type == INTERVAL_MICROSECOND ||
|
|
||||||
(int_type >= INTERVAL_DAY_MICROSECOND &&
|
|
||||||
int_type <= INTERVAL_SECOND_MICROSECOND))
|
|
||||||
interval_dec= TIME_SECOND_PART_DIGITS;
|
|
||||||
else if (int_type == INTERVAL_SECOND && args[1]->decimals > 0)
|
|
||||||
interval_dec= MY_MIN(args[1]->decimals, TIME_SECOND_PART_DIGITS);
|
|
||||||
|
|
||||||
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
|
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
|
set_func_handler(&func_handler_date_add_interval_datetime);
|
||||||
set_handler(&type_handler_datetime);
|
|
||||||
fix_attributes_datetime(dec);
|
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
set_func_handler(&func_handler_date_add_interval_date);
|
||||||
set_handler(&type_handler_newdate);
|
|
||||||
fix_attributes_date();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
set_func_handler(&func_handler_date_add_interval_datetime);
|
||||||
set_handler(&type_handler_datetime2);
|
|
||||||
fix_attributes_datetime(interval_dec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->time_precision(), interval_dec);
|
|
||||||
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
|
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
|
||||||
{
|
set_func_handler(&func_handler_date_add_interval_time);
|
||||||
set_handler(&type_handler_time2);
|
|
||||||
fix_attributes_time(dec);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
set_func_handler(&func_handler_date_add_interval_datetime_arg0_time);
|
||||||
set_handler(&type_handler_datetime2);
|
|
||||||
fix_attributes_datetime(dec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
|
set_func_handler(&func_handler_date_add_interval_string);
|
||||||
set_handler(&type_handler_string);
|
|
||||||
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
|
||||||
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
|
||||||
}
|
}
|
||||||
maybe_null= true;
|
maybe_null= true;
|
||||||
return FALSE;
|
return m_func_handler->fix_length_and_dec(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
bool Func_handler_date_add_interval_datetime_arg0_time::
|
||||||
|
get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
{
|
{
|
||||||
INTERVAL interval;
|
THD *thd= current_thd;
|
||||||
|
// time_expr + INTERVAL {YEAR|QUARTER|MONTH|WEEK|YEAR_MONTH}
|
||||||
if (field_type() == MYSQL_TYPE_TIME)
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||||
{
|
ER_DATETIME_FUNCTION_OVERFLOW,
|
||||||
Time t(args[0]);
|
ER_THD(thd, ER_DATETIME_FUNCTION_OVERFLOW), "time");
|
||||||
if (!t.is_valid_time())
|
return (item->null_value= true);
|
||||||
return (null_value= true);
|
|
||||||
t.copy_to_mysql_time(ltime);
|
|
||||||
}
|
|
||||||
else if (field_type() == MYSQL_TYPE_DATETIME)
|
|
||||||
{
|
|
||||||
THD *thd= current_thd;
|
|
||||||
if (args[0]->field_type() == MYSQL_TYPE_TIME)
|
|
||||||
{
|
|
||||||
// time_expr + INTERVAL {YEAR|QUARTER|MONTH|WEEK|YEAR_MONTH}
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
|
||||||
ER_DATETIME_FUNCTION_OVERFLOW,
|
|
||||||
ER_THD(thd, ER_DATETIME_FUNCTION_OVERFLOW),
|
|
||||||
"time");
|
|
||||||
return (null_value= true);
|
|
||||||
}
|
|
||||||
Datetime dt(thd, args[0], 0);
|
|
||||||
if (!dt.is_valid_datetime())
|
|
||||||
return (null_value= true);
|
|
||||||
dt.copy_to_mysql_time(ltime);
|
|
||||||
}
|
|
||||||
else if (field_type() == MYSQL_TYPE_DATE)
|
|
||||||
{
|
|
||||||
Date d(current_thd, args[0], 0);
|
|
||||||
if (!d.is_valid_date())
|
|
||||||
return (null_value= true);
|
|
||||||
d.copy_to_mysql_time(ltime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (args[0]->get_date(ltime, 0))
|
|
||||||
return (null_value=true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_interval_value(args[1], int_type, &interval))
|
|
||||||
return (null_value= true);
|
|
||||||
|
|
||||||
if (ltime->time_type != MYSQL_TIMESTAMP_TIME &&
|
|
||||||
check_date_with_warn(ltime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE,
|
|
||||||
MYSQL_TIMESTAMP_ERROR))
|
|
||||||
return (null_value=1);
|
|
||||||
|
|
||||||
if (date_sub_interval)
|
|
||||||
interval.neg = !interval.neg;
|
|
||||||
|
|
||||||
if (date_add_interval(ltime, int_type, interval))
|
|
||||||
return (null_value=1);
|
|
||||||
return (null_value= 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2700,69 +2653,22 @@ bool Item_func_add_time::fix_length_and_dec()
|
|||||||
arg0_field_type == MYSQL_TYPE_DATETIME ||
|
arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->datetime_precision(), args[1]->time_precision());
|
set_func_handler(sign > 0 ? &func_handler_add_time_datetime_add :
|
||||||
set_handler(&type_handler_datetime2);
|
&func_handler_add_time_datetime_sub);
|
||||||
fix_attributes_datetime(dec);
|
|
||||||
}
|
}
|
||||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
|
set_func_handler(sign > 0 ? &func_handler_add_time_time_add :
|
||||||
set_handler(&type_handler_time2);
|
&func_handler_add_time_time_sub);
|
||||||
fix_attributes_time(dec);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint dec= MY_MAX(args[0]->decimals, args[1]->decimals);
|
set_func_handler(sign > 0 ? &func_handler_add_time_string_add :
|
||||||
set_handler(&type_handler_string);
|
&func_handler_add_time_string_sub);
|
||||||
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
|
||||||
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_null= true;
|
maybe_null= true;
|
||||||
return FALSE;
|
return m_func_handler->fix_length_and_dec(this);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
|
|
||||||
time/datetime value
|
|
||||||
|
|
||||||
t: time_or_datetime_expression
|
|
||||||
a: time_expression
|
|
||||||
|
|
||||||
Result: Time value or datetime value
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(fixed == 1);
|
|
||||||
MYSQL_TIME l_time2;
|
|
||||||
|
|
||||||
if (Item_func_add_time::field_type() == MYSQL_TYPE_DATETIME)
|
|
||||||
{
|
|
||||||
// TIMESTAMP function OR the first argument is DATE/DATETIME/TIMESTAMP
|
|
||||||
Datetime dt(current_thd, args[0], 0);
|
|
||||||
return (null_value= (!dt.is_valid_datetime() ||
|
|
||||||
args[1]->get_time(&l_time2) ||
|
|
||||||
Sec6_add(dt.get_mysql_time(), &l_time2, sign).
|
|
||||||
to_datetime(ltime)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Item_func_add_time::field_type() == MYSQL_TYPE_TIME)
|
|
||||||
{
|
|
||||||
// ADDTIME() and the first argument is TIME
|
|
||||||
Time t(args[0]);
|
|
||||||
return (null_value= (!t.is_valid_time() ||
|
|
||||||
args[1]->get_time(&l_time2) ||
|
|
||||||
Sec6_add(t.get_mysql_time(), &l_time2, sign).
|
|
||||||
to_time(ltime, decimals)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect a proper timestamp type based on the argument values
|
|
||||||
MYSQL_TIME l_time1;
|
|
||||||
if (args[0]->get_time(&l_time1) || args[1]->get_time(&l_time2))
|
|
||||||
return (null_value= true);
|
|
||||||
Sec6_add add(&l_time1, &l_time2, sign);
|
|
||||||
return (null_value= (l_time1.time_type == MYSQL_TIMESTAMP_TIME ?
|
|
||||||
add.to_time(ltime, decimals) : add.to_datetime(ltime)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3102,15 +3008,10 @@ void Item_func_get_format::print(String *str, enum_query_type query_type)
|
|||||||
specifiers supported by extract_date_time() function.
|
specifiers supported by extract_date_time() function.
|
||||||
|
|
||||||
@return
|
@return
|
||||||
One of date_time_format_types values:
|
A function handler corresponding the given format
|
||||||
- DATE_TIME_MICROSECOND
|
|
||||||
- DATE_TIME
|
|
||||||
- DATE_ONLY
|
|
||||||
- TIME_MICROSECOND
|
|
||||||
- TIME_ONLY
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static date_time_format_types
|
static const Item_handled_func::Handler *
|
||||||
get_date_time_result_type(const char *format, uint length)
|
get_date_time_result_type(const char *format, uint length)
|
||||||
{
|
{
|
||||||
const char *time_part_frms= "HISThiklrs";
|
const char *time_part_frms= "HISThiklrs";
|
||||||
@ -3137,21 +3038,21 @@ get_date_time_result_type(const char *format, uint length)
|
|||||||
frac_second_used implies time_part_used, and thus we already
|
frac_second_used implies time_part_used, and thus we already
|
||||||
have all types of date-time components and can end our search.
|
have all types of date-time components and can end our search.
|
||||||
*/
|
*/
|
||||||
return DATE_TIME_MICROSECOND;
|
return &func_handler_str_to_date_datetime_usec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't have all three types of date-time components */
|
/* We don't have all three types of date-time components */
|
||||||
if (frac_second_used)
|
if (frac_second_used)
|
||||||
return TIME_MICROSECOND;
|
return &func_handler_str_to_date_time_usec;
|
||||||
if (time_part_used)
|
if (time_part_used)
|
||||||
{
|
{
|
||||||
if (date_part_used)
|
if (date_part_used)
|
||||||
return DATE_TIME;
|
return &func_handler_str_to_date_datetime_sec;
|
||||||
return TIME_ONLY;
|
return &func_handler_str_to_date_time_sec;
|
||||||
}
|
}
|
||||||
return DATE_ONLY;
|
return &func_handler_str_to_date_date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3171,56 +3072,27 @@ bool Item_func_str_to_date::fix_length_and_dec()
|
|||||||
internal_charset= &my_charset_utf8mb4_general_ci;
|
internal_charset= &my_charset_utf8mb4_general_ci;
|
||||||
|
|
||||||
maybe_null= true;
|
maybe_null= true;
|
||||||
set_handler(&type_handler_datetime2);
|
set_func_handler(&func_handler_str_to_date_datetime_usec);
|
||||||
fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
|
|
||||||
|
|
||||||
if ((const_item= args[1]->const_item()))
|
if ((const_item= args[1]->const_item()))
|
||||||
{
|
{
|
||||||
char format_buff[64];
|
StringBuffer<64> format_str;
|
||||||
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
|
|
||||||
String *format= args[1]->val_str(&format_str, &format_converter,
|
String *format= args[1]->val_str(&format_str, &format_converter,
|
||||||
internal_charset);
|
internal_charset);
|
||||||
decimals= 0;
|
|
||||||
if (!args[1]->null_value)
|
if (!args[1]->null_value)
|
||||||
{
|
set_func_handler(get_date_time_result_type(format->ptr(), format->length()));
|
||||||
date_time_format_types cached_format_type=
|
|
||||||
get_date_time_result_type(format->ptr(), format->length());
|
|
||||||
switch (cached_format_type) {
|
|
||||||
case DATE_ONLY:
|
|
||||||
set_handler(&type_handler_newdate);
|
|
||||||
fix_attributes_date();
|
|
||||||
break;
|
|
||||||
case TIME_MICROSECOND:
|
|
||||||
set_handler(&type_handler_time2);
|
|
||||||
fix_attributes_time(TIME_SECOND_PART_DIGITS);
|
|
||||||
break;
|
|
||||||
case TIME_ONLY:
|
|
||||||
set_handler(&type_handler_time2);
|
|
||||||
fix_attributes_time(0);
|
|
||||||
break;
|
|
||||||
case DATE_TIME_MICROSECOND:
|
|
||||||
set_handler(&type_handler_datetime2);
|
|
||||||
fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
|
|
||||||
break;
|
|
||||||
case DATE_TIME:
|
|
||||||
set_handler(&type_handler_datetime2);
|
|
||||||
fix_attributes_datetime(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cached_timestamp_type= mysql_timestamp_type();
|
return m_func_handler->fix_length_and_dec(this);
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
bool Item_func_str_to_date::get_date_common(MYSQL_TIME *ltime,
|
||||||
|
ulonglong fuzzy_date,
|
||||||
|
timestamp_type tstype)
|
||||||
{
|
{
|
||||||
DATE_TIME_FORMAT date_time_format;
|
DATE_TIME_FORMAT date_time_format;
|
||||||
char val_buff[64], format_buff[64];
|
StringBuffer<64> val_string, format_str;
|
||||||
String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
|
String *val, *format;
|
||||||
String format_str(format_buff, sizeof(format_buff), &my_charset_bin),
|
|
||||||
*format;
|
|
||||||
|
|
||||||
val= args[0]->val_str(&val_string, &subject_converter, internal_charset);
|
val= args[0]->val_str(&val_string, &subject_converter, internal_charset);
|
||||||
format= args[1]->val_str(&format_str, &format_converter, internal_charset);
|
format= args[1]->val_str(&format_str, &format_converter, internal_charset);
|
||||||
@ -3230,19 +3102,9 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
|||||||
date_time_format.format.str= (char*) format->ptr();
|
date_time_format.format.str= (char*) format->ptr();
|
||||||
date_time_format.format.length= format->length();
|
date_time_format.format.length= format->length();
|
||||||
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
|
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
|
||||||
ltime, cached_timestamp_type, 0, "datetime",
|
ltime, tstype, 0, "datetime",
|
||||||
fuzzy_date | sql_mode_for_dates(current_thd)))
|
fuzzy_date | sql_mode_for_dates(current_thd)))
|
||||||
return (null_value=1);
|
return (null_value=1);
|
||||||
if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Day part for time type can be nonzero value and so
|
|
||||||
we should add hours from day part to hour part to
|
|
||||||
keep valid time value.
|
|
||||||
*/
|
|
||||||
ltime->hour+= ltime->day*24;
|
|
||||||
ltime->day= 0;
|
|
||||||
}
|
|
||||||
return (null_value= 0);
|
return (null_value= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,6 @@
|
|||||||
|
|
||||||
class MY_LOCALE;
|
class MY_LOCALE;
|
||||||
|
|
||||||
enum date_time_format_types
|
|
||||||
{
|
|
||||||
TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
|
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
|
||||||
|
|
||||||
@ -602,38 +597,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Abstract class for functions returning TIME, DATE, DATETIME or string values,
|
|
||||||
whose data type depends on parameters and is set at fix_fields time.
|
|
||||||
*/
|
|
||||||
class Item_temporal_hybrid_func: public Item_hybrid_func
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
String ascii_buf; // Conversion buffer
|
|
||||||
public:
|
|
||||||
Item_temporal_hybrid_func(THD *thd, Item *a, Item *b):
|
|
||||||
Item_hybrid_func(thd, a, b) {}
|
|
||||||
|
|
||||||
longlong val_int() { return val_int_from_date(); }
|
|
||||||
double val_real() { return val_real_from_date(); }
|
|
||||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)= 0;
|
|
||||||
my_decimal *val_decimal(my_decimal *decimal_value)
|
|
||||||
{ return val_decimal_from_date(decimal_value); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return string value in ASCII character set.
|
|
||||||
*/
|
|
||||||
String *val_str_ascii(String *str);
|
|
||||||
/**
|
|
||||||
Return string value in @@character_set_connection.
|
|
||||||
*/
|
|
||||||
String *val_str(String *str)
|
|
||||||
{
|
|
||||||
return val_str_from_val_str_ascii(str, &ascii_buf);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Item_datefunc :public Item_temporal_func
|
class Item_datefunc :public Item_temporal_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -985,18 +948,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_date_add_interval :public Item_temporal_hybrid_func
|
class Item_date_add_interval :public Item_handled_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const interval_type int_type; // keep it public
|
const interval_type int_type; // keep it public
|
||||||
const bool date_sub_interval; // keep it public
|
const bool date_sub_interval; // keep it public
|
||||||
Item_date_add_interval(THD *thd, Item *a, Item *b, interval_type type_arg,
|
Item_date_add_interval(THD *thd, Item *a, Item *b, interval_type type_arg,
|
||||||
bool neg_arg):
|
bool neg_arg):
|
||||||
Item_temporal_hybrid_func(thd, a, b),int_type(type_arg),
|
Item_handled_func(thd, a, b), int_type(type_arg),
|
||||||
date_sub_interval(neg_arg) {}
|
date_sub_interval(neg_arg) {}
|
||||||
const char *func_name() const { return "date_add_interval"; }
|
const char *func_name() const { return "date_add_interval"; }
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
|
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
bool eq(const Item *item, bool binary_cmp) const;
|
||||||
void print(String *str, enum_query_type query_type);
|
void print(String *str, enum_query_type query_type);
|
||||||
enum precedence precedence() const { return ADDINTERVAL_PRECEDENCE; }
|
enum precedence precedence() const { return ADDINTERVAL_PRECEDENCE; }
|
||||||
@ -1264,20 +1226,30 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_add_time :public Item_temporal_hybrid_func
|
/**
|
||||||
|
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
|
||||||
|
time/datetime value
|
||||||
|
|
||||||
|
t: time_or_datetime_expression
|
||||||
|
a: time_expression
|
||||||
|
|
||||||
|
Result: Time value or datetime value
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Item_func_add_time :public Item_handled_func
|
||||||
{
|
{
|
||||||
int sign;
|
int sign;
|
||||||
public:
|
public:
|
||||||
Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg)
|
Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg)
|
||||||
:Item_temporal_hybrid_func(thd, a, b), sign(neg_arg ? -1 : 1)
|
:Item_handled_func(thd, a, b), sign(neg_arg ? -1 : 1)
|
||||||
{ }
|
{ }
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
|
||||||
const char *func_name() const { return sign > 0 ? "addtime" : "subtime"; }
|
const char *func_name() const { return sign > 0 ? "addtime" : "subtime"; }
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_add_time>(thd, this); }
|
{ return get_item_copy<Item_func_add_time>(thd, this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_timediff :public Item_timefunc
|
class Item_func_timediff :public Item_timefunc
|
||||||
{
|
{
|
||||||
bool check_arguments() const
|
bool check_arguments() const
|
||||||
@ -1394,19 +1366,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_str_to_date :public Item_temporal_hybrid_func
|
class Item_func_str_to_date :public Item_handled_func
|
||||||
{
|
{
|
||||||
timestamp_type cached_timestamp_type;
|
|
||||||
bool const_item;
|
bool const_item;
|
||||||
String subject_converter;
|
String subject_converter;
|
||||||
String format_converter;
|
String format_converter;
|
||||||
CHARSET_INFO *internal_charset;
|
CHARSET_INFO *internal_charset;
|
||||||
public:
|
public:
|
||||||
Item_func_str_to_date(THD *thd, Item *a, Item *b):
|
Item_func_str_to_date(THD *thd, Item *a, Item *b):
|
||||||
Item_temporal_hybrid_func(thd, a, b), const_item(false),
|
Item_handled_func(thd, a, b), const_item(false),
|
||||||
internal_charset(NULL)
|
internal_charset(NULL)
|
||||||
{}
|
{}
|
||||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
bool get_date_common(MYSQL_TIME *ltime, ulonglong fuzzy_date, timestamp_type);
|
||||||
const char *func_name() const { return "str_to_date"; }
|
const char *func_name() const { return "str_to_date"; }
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
@ -1426,4 +1397,398 @@ public:
|
|||||||
{ return get_item_copy<Item_func_last_day>(thd, this); }
|
{ return get_item_copy<Item_func_last_day>(thd, this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
Abstract class for functions returning TIME, DATE, DATETIME or string values,
|
||||||
|
whose data type depends on parameters and is set at fix_fields time.
|
||||||
|
*/
|
||||||
|
class Func_handler_temporal_hybrid: public Item_handled_func::Handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double val_real(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
return item->val_real_from_date();
|
||||||
|
}
|
||||||
|
longlong val_int(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
return item->val_int_from_date();
|
||||||
|
}
|
||||||
|
my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const
|
||||||
|
{
|
||||||
|
return item->val_decimal_from_date(to);
|
||||||
|
}
|
||||||
|
String *val_str(Item_handled_func *item, String *to) const
|
||||||
|
{
|
||||||
|
StringBuffer<MAX_FIELD_WIDTH> ascii_buf;
|
||||||
|
return item->val_str_from_val_str_ascii(to, &ascii_buf);
|
||||||
|
}
|
||||||
|
String *val_str_ascii(Item_handled_func *, String *to) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval: public Func_handler_temporal_hybrid
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
static uint interval_dec(const Item *item, interval_type int_type)
|
||||||
|
{
|
||||||
|
if (int_type == INTERVAL_MICROSECOND ||
|
||||||
|
(int_type >= INTERVAL_DAY_MICROSECOND &&
|
||||||
|
int_type <= INTERVAL_SECOND_MICROSECOND))
|
||||||
|
return TIME_SECOND_PART_DIGITS;
|
||||||
|
if (int_type == INTERVAL_SECOND && item->decimals > 0)
|
||||||
|
return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
interval_type int_type(const Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
return static_cast<const Item_date_add_interval*>(item)->int_type;
|
||||||
|
}
|
||||||
|
bool sub(const Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
return static_cast<const Item_date_add_interval*>(item)->date_sub_interval;
|
||||||
|
}
|
||||||
|
bool add(Item *item, interval_type type, bool sub, MYSQL_TIME *to) const
|
||||||
|
{
|
||||||
|
INTERVAL interval;
|
||||||
|
if (get_interval_value(item, type, &interval))
|
||||||
|
return true;
|
||||||
|
if (sub)
|
||||||
|
interval.neg = !interval.neg;
|
||||||
|
return date_add_interval(to, type, interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval_datetime:
|
||||||
|
public Func_handler_date_add_interval
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_datetime2;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->datetime_precision(),
|
||||||
|
interval_dec(item->arguments()[1], int_type(item)));
|
||||||
|
item->fix_attributes_datetime(dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
Datetime dt(current_thd, item->arguments()[0], 0);
|
||||||
|
if (!dt.is_valid_datetime() ||
|
||||||
|
dt.check_date_with_warn(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
|
||||||
|
return (item->null_value= true);
|
||||||
|
dt.copy_to_mysql_time(to);
|
||||||
|
return (item->null_value= add(item->arguments()[1],
|
||||||
|
int_type(item), sub(item), to));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval_datetime_arg0_time:
|
||||||
|
public Func_handler_date_add_interval_datetime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval_date: public Func_handler_date_add_interval
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_newdate;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_date();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
Date d(current_thd, item->arguments()[0], 0);
|
||||||
|
if (!d.is_valid_date() ||
|
||||||
|
d.check_date_with_warn(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
|
||||||
|
return (item->null_value= true);
|
||||||
|
d.copy_to_mysql_time(to);
|
||||||
|
return (item->null_value= add(item->arguments()[1],
|
||||||
|
int_type(item), sub(item), to));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval_time: public Func_handler_date_add_interval
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_time2;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->time_precision(),
|
||||||
|
interval_dec(item->arguments()[1], int_type(item)));
|
||||||
|
item->fix_attributes_time(dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
Time t(item->arguments()[0]);
|
||||||
|
if (!t.is_valid_time())
|
||||||
|
return (item->null_value= true);
|
||||||
|
t.copy_to_mysql_time(to);
|
||||||
|
return (item->null_value= add(item->arguments()[1],
|
||||||
|
int_type(item), sub(item), to));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_date_add_interval_string:
|
||||||
|
public Func_handler_date_add_interval
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_string;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->datetime_precision(),
|
||||||
|
interval_dec(item->arguments()[1], int_type(item)));
|
||||||
|
item->collation.set(item->default_charset(),
|
||||||
|
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
||||||
|
item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
if (item->arguments()[0]->get_date(to, 0) ||
|
||||||
|
(to->time_type != MYSQL_TIMESTAMP_TIME &&
|
||||||
|
check_date_with_warn(to, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE,
|
||||||
|
MYSQL_TIMESTAMP_ERROR)))
|
||||||
|
return (item->null_value= true);
|
||||||
|
return (item->null_value= add(item->arguments()[1],
|
||||||
|
int_type(item), sub(item), to));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_add_time: public Func_handler_temporal_hybrid
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int m_sign;
|
||||||
|
Func_handler_add_time(int sign) :m_sign(sign) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_add_time_datetime: public Func_handler_add_time
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Func_handler_add_time_datetime(int sign)
|
||||||
|
:Func_handler_add_time(sign)
|
||||||
|
{ }
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_datetime2;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->datetime_precision(),
|
||||||
|
item->arguments()[1]->time_precision());
|
||||||
|
item->fix_attributes_datetime(dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->is_fixed());
|
||||||
|
MYSQL_TIME l_time2;
|
||||||
|
Datetime dt(current_thd, item->arguments()[0], 0);
|
||||||
|
return (item->null_value= (!dt.is_valid_datetime() ||
|
||||||
|
item->arguments()[1]->get_time(&l_time2) ||
|
||||||
|
Sec6_add(dt.get_mysql_time(), &l_time2, m_sign).
|
||||||
|
to_datetime(to)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_add_time_time: public Func_handler_add_time
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Func_handler_add_time_time(int sign)
|
||||||
|
:Func_handler_add_time(sign)
|
||||||
|
{ }
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_time2;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->time_precision(),
|
||||||
|
item->arguments()[1]->time_precision());
|
||||||
|
item->fix_attributes_time(dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->is_fixed());
|
||||||
|
MYSQL_TIME l_time2;
|
||||||
|
Time t(item->arguments()[0]);
|
||||||
|
return (item->null_value= (!t.is_valid_time() ||
|
||||||
|
item->arguments()[1]->get_time(&l_time2) ||
|
||||||
|
Sec6_add(t.get_mysql_time(), &l_time2, m_sign).
|
||||||
|
to_time(to, item->decimals)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_add_time_string: public Func_handler_add_time
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Func_handler_add_time_string(int sign)
|
||||||
|
:Func_handler_add_time(sign)
|
||||||
|
{ }
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_string;
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
uint dec= MY_MAX(item->arguments()[0]->decimals,
|
||||||
|
item->arguments()[1]->decimals);
|
||||||
|
item->collation.set(item->default_charset(),
|
||||||
|
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
||||||
|
item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->is_fixed());
|
||||||
|
// Detect a proper timestamp type based on the argument values
|
||||||
|
MYSQL_TIME l_time1, l_time2;
|
||||||
|
if (item->arguments()[0]->get_time(&l_time1) ||
|
||||||
|
item->arguments()[1]->get_time(&l_time2))
|
||||||
|
return (item->null_value= true);
|
||||||
|
Sec6_add add(&l_time1, &l_time2, m_sign);
|
||||||
|
return (item->null_value= (l_time1.time_type == MYSQL_TIMESTAMP_TIME ?
|
||||||
|
add.to_time(to, item->decimals) :
|
||||||
|
add.to_datetime(to)));
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_datetime: public Func_handler_temporal_hybrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_datetime2;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
return static_cast<Item_func_str_to_date*>(item)->
|
||||||
|
get_date_common(to, fuzzy, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_datetime_sec:
|
||||||
|
public Func_handler_str_to_date_datetime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_datetime(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_datetime_usec:
|
||||||
|
public Func_handler_str_to_date_datetime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_date: public Func_handler_temporal_hybrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_newdate;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
return static_cast<Item_func_str_to_date*>(item)->
|
||||||
|
get_date_common(to, fuzzy, MYSQL_TIMESTAMP_DATE);
|
||||||
|
}
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_date();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_time: public Func_handler_temporal_hybrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *return_type_handler() const
|
||||||
|
{
|
||||||
|
return &type_handler_time2;
|
||||||
|
}
|
||||||
|
bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const
|
||||||
|
{
|
||||||
|
if (static_cast<Item_func_str_to_date*>(item)->
|
||||||
|
get_date_common(to, fuzzy, MYSQL_TIMESTAMP_TIME))
|
||||||
|
return true;
|
||||||
|
if (to->day)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Day part for time type can be nonzero value and so
|
||||||
|
we should add hours from day part to hour part to
|
||||||
|
keep valid time value.
|
||||||
|
*/
|
||||||
|
to->hour+= to->day * 24;
|
||||||
|
to->day= 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_time_sec: public Func_handler_str_to_date_time
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_time(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Func_handler_str_to_date_time_usec: public Func_handler_str_to_date_time
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool fix_length_and_dec(Item_handled_func *item) const
|
||||||
|
{
|
||||||
|
item->fix_attributes_time(TIME_SECOND_PART_DIGITS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* ITEM_TIMEFUNC_INCLUDED */
|
#endif /* ITEM_TIMEFUNC_INCLUDED */
|
||||||
|
@ -367,6 +367,11 @@ protected:
|
|||||||
{
|
{
|
||||||
make_from_item(thd, item, flags);
|
make_from_item(thd, item, flags);
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
bool check_date_with_warn(ulonglong flags)
|
||||||
|
{
|
||||||
|
return ::check_date_with_warn(this, flags, MYSQL_TIMESTAMP_ERROR);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user