mirror of
https://github.com/MariaDB/server.git
synced 2026-05-02 21:25:36 +02:00
Merge from 5.3.
pending merges: Alexander Barkov 2013-09-12 MDEV-4724 Some temporal functions do not pre...
This commit is contained in:
commit
51dcf4dcff
23 changed files with 490 additions and 185 deletions
38
sql/item.cc
38
sql/item.cc
|
|
@ -537,6 +537,44 @@ uint Item::decimal_precision() const
|
|||
}
|
||||
|
||||
|
||||
#if MARIADB_VERSION_ID < 1000000
|
||||
static uint ms_to_precision(uint ms)
|
||||
{
|
||||
uint cut, precision;
|
||||
for (cut= 10, precision= 6 ; precision > 0 ; cut*= 10, precision--)
|
||||
{
|
||||
if (ms % cut)
|
||||
return precision;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#error Change the code to use MYSQL_TIME_STATUS::precision instead.
|
||||
#endif
|
||||
|
||||
|
||||
uint Item::temporal_precision(enum_field_types type)
|
||||
{
|
||||
if (const_item() && result_type() == STRING_RESULT &&
|
||||
!is_temporal_type(field_type()))
|
||||
{
|
||||
MYSQL_TIME ltime;
|
||||
String buf, *tmp;
|
||||
int was_cut;
|
||||
DBUG_ASSERT(fixed);
|
||||
if ((tmp= val_str(&buf)) &&
|
||||
(type == MYSQL_TYPE_TIME ?
|
||||
str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
|
||||
<ime, TIME_TIME_ONLY, &was_cut) :
|
||||
str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
|
||||
<ime, TIME_FUZZY_DATES, &was_cut)) >
|
||||
MYSQL_TIMESTAMP_ERROR)
|
||||
return min(ms_to_precision(ltime.second_part), TIME_SECOND_PART_DIGITS);
|
||||
}
|
||||
return min(decimals, TIME_SECOND_PART_DIGITS);
|
||||
}
|
||||
|
||||
|
||||
void Item::print_item_w_name(String *str, enum_query_type query_type)
|
||||
{
|
||||
print(str, query_type);
|
||||
|
|
|
|||
|
|
@ -1009,6 +1009,10 @@ public:
|
|||
virtual uint decimal_precision() const;
|
||||
inline int decimal_int_part() const
|
||||
{ return my_decimal_int_part(decimal_precision(), decimals); }
|
||||
/**
|
||||
TIME or DATETIME precision of the item: 0..6
|
||||
*/
|
||||
uint temporal_precision(enum_field_types type);
|
||||
/*
|
||||
Returns true if this is constant (during query execution, i.e. its value
|
||||
will not change until next fix_fields) and its value is known.
|
||||
|
|
|
|||
|
|
@ -1809,6 +1809,8 @@ public:
|
|||
double val_real();
|
||||
longlong val_int();
|
||||
String* val_str(String*);
|
||||
my_decimal *val_decimal(my_decimal *dec_buf)
|
||||
{ return val_decimal_from_real(dec_buf); }
|
||||
/* TODO: fix to support views */
|
||||
const char *func_name() const { return "get_system_var"; }
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1290,7 +1290,19 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
|
|||
String str_value(buf, sizeof(buf), &my_charset_bin);
|
||||
|
||||
bzero((char*) interval,sizeof(*interval));
|
||||
if ((int) int_type <= INTERVAL_MICROSECOND)
|
||||
if (int_type == INTERVAL_SECOND && args->decimals)
|
||||
{
|
||||
my_decimal decimal_value, *val;
|
||||
ulonglong second;
|
||||
ulong second_part;
|
||||
if (!(val= args->val_decimal(&decimal_value)))
|
||||
return true;
|
||||
interval->neg= my_decimal2seconds(val, &second, &second_part);
|
||||
interval->second= second;
|
||||
interval->second_part= second_part;
|
||||
return false;
|
||||
}
|
||||
else if ((int) int_type <= INTERVAL_MICROSECOND)
|
||||
{
|
||||
value= args->val_int();
|
||||
if (args->null_value)
|
||||
|
|
@ -1435,6 +1447,10 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
|
|||
|
||||
void Item_temporal_func::fix_length_and_dec()
|
||||
{
|
||||
/*
|
||||
We set maybe_null to 1 as default as any bad argument with date or
|
||||
time can get us to return NULL.
|
||||
*/
|
||||
set_persist_maybe_null(1);
|
||||
max_length= mysql_temporal_int_part_length(field_type());
|
||||
if (decimals)
|
||||
|
|
@ -1925,7 +1941,7 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
|
|||
|
||||
void Item_func_convert_tz::fix_length_and_dec()
|
||||
{
|
||||
decimals= args[0]->decimals;
|
||||
decimals= args[0]->temporal_precision(MYSQL_TYPE_DATETIME);
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
}
|
||||
|
||||
|
|
@ -1996,28 +2012,40 @@ void Item_date_add_interval::fix_length_and_dec()
|
|||
*/
|
||||
cached_field_type= MYSQL_TYPE_STRING;
|
||||
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= min(args[1]->decimals, TIME_SECOND_PART_DIGITS);
|
||||
|
||||
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
||||
{
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
|
||||
cached_field_type= MYSQL_TYPE_DATETIME;
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_DATE)
|
||||
{
|
||||
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
|
||||
cached_field_type= arg0_field_type;
|
||||
else
|
||||
{
|
||||
decimals= interval_dec;
|
||||
cached_field_type= MYSQL_TYPE_DATETIME;
|
||||
}
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||
{
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
|
||||
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
|
||||
cached_field_type= arg0_field_type;
|
||||
else
|
||||
cached_field_type= MYSQL_TYPE_DATETIME;
|
||||
}
|
||||
if (int_type == INTERVAL_MICROSECOND || int_type >= INTERVAL_DAY_MICROSECOND)
|
||||
decimals= 6;
|
||||
else
|
||||
decimals= args[0]->decimals;
|
||||
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
}
|
||||
|
||||
|
|
@ -2531,9 +2559,17 @@ void Item_func_add_time::fix_length_and_dec()
|
|||
if (arg0_field_type == MYSQL_TYPE_DATE ||
|
||||
arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
||||
{
|
||||
cached_field_type= MYSQL_TYPE_DATETIME;
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||
{
|
||||
cached_field_type= MYSQL_TYPE_TIME;
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
}
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
}
|
||||
|
||||
|
|
@ -2714,13 +2750,14 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
|||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
bool overflow= 0;
|
||||
|
||||
longlong hour= args[0]->val_int();
|
||||
longlong minute= args[1]->val_int();
|
||||
longlong second= args[2]->val_int();
|
||||
ulonglong second;
|
||||
ulong microsecond;
|
||||
bool neg= args[2]->get_seconds(&second, µsecond);
|
||||
|
||||
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
|
||||
minute < 0 || minute > 59 || second < 0 || second > 59)
|
||||
minute < 0 || minute > 59 || neg || second > 59)
|
||||
return (null_value= 1);
|
||||
|
||||
bzero(ltime, sizeof(*ltime));
|
||||
|
|
@ -2742,6 +2779,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
|||
ltime->hour= (uint) ((hour < 0 ? -hour : hour));
|
||||
ltime->minute= (uint) minute;
|
||||
ltime->second= (uint) second;
|
||||
ltime->second_part= microsecond;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -408,13 +408,15 @@ class Item_func_dayname :public Item_func_weekday
|
|||
|
||||
class Item_func_seconds_hybrid: public Item_func_numhybrid
|
||||
{
|
||||
protected:
|
||||
virtual enum_field_types arg0_expected_type() const = 0;
|
||||
public:
|
||||
Item_func_seconds_hybrid() :Item_func_numhybrid() {}
|
||||
Item_func_seconds_hybrid(Item *a) :Item_func_numhybrid(a) {}
|
||||
void fix_num_length_and_dec()
|
||||
{
|
||||
if (arg_count)
|
||||
decimals= args[0]->decimals;
|
||||
decimals= args[0]->temporal_precision(arg0_expected_type());
|
||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||
max_length=17 + (decimals ? decimals + 1 : 0);
|
||||
set_persist_maybe_null(1);
|
||||
|
|
@ -430,6 +432,8 @@ public:
|
|||
class Item_func_unix_timestamp :public Item_func_seconds_hybrid
|
||||
{
|
||||
bool get_timestamp_value(my_time_t *seconds, ulong *second_part);
|
||||
protected:
|
||||
enum_field_types arg0_expected_type() const { return MYSQL_TYPE_DATETIME; }
|
||||
public:
|
||||
Item_func_unix_timestamp() :Item_func_seconds_hybrid() {}
|
||||
Item_func_unix_timestamp(Item *a) :Item_func_seconds_hybrid(a) {}
|
||||
|
|
@ -461,6 +465,8 @@ public:
|
|||
|
||||
class Item_func_time_to_sec :public Item_func_seconds_hybrid
|
||||
{
|
||||
protected:
|
||||
enum_field_types arg0_expected_type() const { return MYSQL_TYPE_TIME; }
|
||||
public:
|
||||
Item_func_time_to_sec(Item *item) :Item_func_seconds_hybrid(item) {}
|
||||
const char *func_name() const { return "time_to_sec"; }
|
||||
|
|
@ -860,7 +866,7 @@ public:
|
|||
void fix_length_and_dec()
|
||||
{
|
||||
if (decimals == NOT_FIXED_DEC)
|
||||
decimals= args[0]->decimals;
|
||||
decimals= args[0]->temporal_precision(field_type());
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
}
|
||||
};
|
||||
|
|
@ -934,7 +940,8 @@ public:
|
|||
const char *func_name() const { return "timediff"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||
decimals= max(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
Item_timefunc::fix_length_and_dec();
|
||||
}
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
||||
|
|
@ -946,6 +953,11 @@ public:
|
|||
Item_func_maketime(Item *a, Item *b, Item *c)
|
||||
:Item_timefunc(a, b, c)
|
||||
{}
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals= min(args[2]->decimals, TIME_SECOND_PART_DIGITS);
|
||||
Item_timefunc::fix_length_and_dec();
|
||||
}
|
||||
const char *func_name() const { return "maketime"; }
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue