summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/item.cc21
-rw-r--r--sql/item.h11
-rw-r--r--sql/item_timefunc.cc21
-rw-r--r--sql/item_timefunc.h37
-rw-r--r--sql/sql_type.cc49
-rw-r--r--sql/sql_type.h11
6 files changed, 88 insertions, 62 deletions
diff --git a/sql/item.cc b/sql/item.cc
index b99b3a23c8a..0456adc3fb1 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -555,27 +555,6 @@ uint Item::decimal_precision() const
}
-uint Item::temporal_precision(enum_field_types type_arg)
-{
- if (const_item() && result_type() == STRING_RESULT &&
- !is_temporal_type(field_type()))
- {
- MYSQL_TIME ltime;
- String buf, *tmp;
- MYSQL_TIME_STATUS status;
- DBUG_ASSERT(fixed);
- if ((tmp= val_str(&buf)) &&
- !(type_arg == MYSQL_TYPE_TIME ?
- str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_TIME_ONLY, &status) :
- str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_FUZZY_DATES, &status)))
- return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
- }
- return MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
-}
-
-
void Item::print_parenthesised(String *str, enum_query_type query_type,
enum precedence parent_prec)
{
diff --git a/sql/item.h b/sql/item.h
index bd24b64d99a..6c6714a5351 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1187,7 +1187,16 @@ public:
/**
TIME or DATETIME precision of the item: 0..6
*/
- uint temporal_precision(enum_field_types type);
+ uint time_precision()
+ {
+ return const_item() ? type_handler()->Item_time_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ uint datetime_precision()
+ {
+ return const_item() ? type_handler()->Item_datetime_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
/*
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.
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a4a1f900fce..d637fa12ad1 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2009,13 +2009,6 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
}
-void Item_func_convert_tz::fix_length_and_dec()
-{
- fix_attributes_datetime(args[0]->temporal_precision(MYSQL_TYPE_DATETIME));
- maybe_null= true;
-}
-
-
bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime,
ulonglong fuzzy_date __attribute__((unused)))
{
@@ -2099,8 +2092,7 @@ void Item_date_add_interval::fix_length_and_dec()
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
- interval_dec);
+ uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
set_handler(&type_handler_datetime);
fix_attributes_datetime(dec);
}
@@ -2119,7 +2111,7 @@ void Item_date_add_interval::fix_length_and_dec()
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
+ uint dec= MY_MAX(args[0]->time_precision(), interval_dec);
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
{
set_handler(&type_handler_time2);
@@ -2133,8 +2125,7 @@ void Item_date_add_interval::fix_length_and_dec()
}
else
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
- interval_dec);
+ uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
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);
@@ -2669,15 +2660,13 @@ void Item_func_add_time::fix_length_and_dec()
arg0_field_type == MYSQL_TYPE_TIMESTAMP ||
is_date)
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->datetime_precision(), args[1]->time_precision());
set_handler(&type_handler_datetime2);
fix_attributes_datetime(dec);
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
set_handler(&type_handler_time2);
fix_attributes_time(dec);
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 40b8c169c80..5caeea489f6 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -443,16 +443,13 @@ 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(THD *thd): Item_func_numhybrid(thd) {}
Item_func_seconds_hybrid(THD *thd, Item *a): Item_func_numhybrid(thd, a) {}
- void fix_length_and_dec()
+ void fix_length_and_dec_generic(uint dec)
{
- if (arg_count)
- decimals= args[0]->temporal_precision(arg0_expected_type());
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ decimals= dec;
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT);
@@ -466,8 +463,6 @@ 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(THD *thd): Item_func_seconds_hybrid(thd) {}
Item_func_unix_timestamp(THD *thd, Item *a):
@@ -491,6 +486,10 @@ public:
return FALSE;
return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
}
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -500,8 +499,6 @@ 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(THD *thd, Item *item):
Item_func_seconds_hybrid(thd, item) {}
@@ -512,6 +509,10 @@ public:
{
return !has_time_args();
}
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(args[0]->time_precision());
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -864,7 +865,11 @@ class Item_func_convert_tz :public Item_datetimefunc
Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c):
Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {}
const char *func_name() const { return "convert_tz"; }
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ fix_attributes_datetime(args[0]->datetime_precision());
+ maybe_null= true;
+ }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void cleanup();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1059,13 +1064,6 @@ public:
Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {}
virtual const char *cast_type() const = 0;
void print(String *str, enum_query_type query_type);
- void fix_length_and_dec_generic(uint int_part_len)
- {
- if (decimals == NOT_FIXED_DEC)
- decimals= args[0]->temporal_precision(field_type());
- fix_attributes_temporal(int_part_len, decimals);
- maybe_null= true;
- }
};
class Item_date_typecast :public Item_temporal_typecast
@@ -1157,8 +1155,7 @@ public:
const char *func_name() const { return "timediff"; }
void fix_length_and_dec()
{
- uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
fix_attributes_time(dec);
maybe_null= true;
}
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index cf5e4e46400..a2994c74250 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -17,6 +17,7 @@
#include "sql_type.h"
#include "sql_const.h"
#include "sql_class.h"
+#include "sql_time.h"
#include "item.h"
#include "log.h"
@@ -2689,7 +2690,11 @@ bool Type_handler_numeric::
bool Type_handler::
Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
{
- item->fix_length_and_dec_generic(MIN_TIME_WIDTH);
+ uint dec= item->decimals == NOT_FIXED_DEC ?
+ item->arguments()[0]->time_precision() :
+ item->decimals;
+ item->fix_attributes_temporal(MIN_TIME_WIDTH, dec);
+ item->maybe_null= true;
return false;
}
@@ -2697,7 +2702,8 @@ bool Type_handler::
bool Type_handler::
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
{
- item->fix_length_and_dec_generic(MAX_DATE_WIDTH);
+ item->fix_attributes_temporal(MAX_DATE_WIDTH, 0);
+ item->maybe_null= true;
return false;
}
@@ -2706,9 +2712,12 @@ bool Type_handler::
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
const
{
- item->fix_length_and_dec_generic(MAX_DATETIME_WIDTH);
+ uint dec= item->decimals == NOT_FIXED_DEC ?
+ item->arguments()[0]->datetime_precision() :
+ item->decimals;
+ item->fix_attributes_temporal(MAX_DATETIME_WIDTH, dec);
+ item->maybe_null= true;
return false;
-
}
@@ -3023,3 +3032,35 @@ bool Type_handler_string_result::
}
/***************************************************************************/
+
+uint Type_handler::Item_time_precision(Item *item) const
+{
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+
+uint Type_handler::Item_datetime_precision(Item *item) const
+{
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+
+uint Type_handler_string_result::Item_temporal_precision(Item *item,
+ bool is_time) const
+{
+ MYSQL_TIME ltime;
+ StringBuffer<64> buf;
+ String *tmp;
+ MYSQL_TIME_STATUS status;
+ DBUG_ASSERT(item->fixed);
+ if ((tmp= item->val_str(&buf)) &&
+ !(is_time ?
+ str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_TIME_ONLY, &status) :
+ str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_FUZZY_DATES, &status)))
+ return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+/***************************************************************************/
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 43736bddca7..2c8d5df050f 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -389,6 +389,8 @@ public:
{
return true;
}
+ virtual uint Item_time_precision(Item *item) const;
+ virtual uint Item_datetime_precision(Item *item) const;
/**
Makes a temporary table Field to handle numeric aggregate functions,
e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc.
@@ -1040,6 +1042,7 @@ public:
class Type_handler_string_result: public Type_handler
{
+ uint Item_temporal_precision(Item *item, bool is_time) const;
public:
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return STRING_RESULT; }
@@ -1055,6 +1058,14 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
+ uint Item_time_precision(Item *item) const
+ {
+ return Item_temporal_precision(item, true);
+ }
+ uint Item_datetime_precision(Item *item) const
+ {
+ return Item_temporal_precision(item, false);
+ }
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const
{