diff options
-rw-r--r-- | sql/item.cc | 21 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 21 | ||||
-rw-r--r-- | sql/item_timefunc.h | 37 | ||||
-rw-r--r-- | sql/sql_type.cc | 49 | ||||
-rw-r--r-- | sql/sql_type.h | 11 |
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(), - <ime, TIME_TIME_ONLY, &status) : - str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(), - <ime, 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(), + <ime, TIME_TIME_ONLY, &status) : + str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(), + <ime, 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 { |