diff options
author | Alexander Barkov <bar@mnogosearch.org> | 2013-11-21 11:46:36 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mnogosearch.org> | 2013-11-21 11:46:36 +0400 |
commit | 2394fa67d4908f62ef14f3ca90269fb32806d193 (patch) | |
tree | f1b54751a653ab37af221f1b22a5368f5ee05ffc /sql | |
parent | f8a6ee59acb082678cf601a10cbe9c1152748242 (diff) | |
download | mariadb-git-2394fa67d4908f62ef14f3ca90269fb32806d193.tar.gz |
MDEV-4859 Wrong value and data type of "SELECT MAX(time_column) + 1 FROM t1"
Fixed.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 69 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 9 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 21 | ||||
-rw-r--r-- | sql/item_timefunc.h | 4 |
7 files changed, 86 insertions, 27 deletions
diff --git a/sql/item.cc b/sql/item.cc index a415464a2f9..29cfd2d08d1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -350,6 +350,27 @@ my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) } +longlong Item::val_int_from_date() +{ + DBUG_ASSERT(fixed == 1); + MYSQL_TIME ltime; + if (get_date(<ime, 0)) + return 0; + longlong v= TIME_to_ulonglong(<ime); + return ltime.neg ? -v : v; +} + + +double Item::val_real_from_date() +{ + DBUG_ASSERT(fixed == 1); + MYSQL_TIME ltime; + if (get_date(<ime, 0)) + return 0; + return TIME_to_double(<ime); +} + + double Item::val_real_from_decimal() { /* Note that fix_fields may not be called for Item_avg_field items */ @@ -8381,6 +8402,18 @@ int Item_cache_int::save_in_field(Field *field, bool no_conversions) } +longlong Item_cache_temporal::val_temporal_packed() +{ + DBUG_ASSERT(fixed == 1); + if ((!value_cached && !cache_value()) || null_value) + { + null_value= TRUE; + return 0; + } + return value; +} + + String *Item_cache_temporal::val_str(String *str) { DBUG_ASSERT(fixed == 1); @@ -8393,6 +8426,42 @@ String *Item_cache_temporal::val_str(String *str) } +my_decimal *Item_cache_temporal::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + if ((!value_cached && !cache_value()) || null_value) + { + null_value= true; + return NULL; + } + return val_decimal_from_date(decimal_value); +} + + +longlong Item_cache_temporal::val_int() +{ + DBUG_ASSERT(fixed == 1); + if ((!value_cached && !cache_value()) || null_value) + { + null_value= true; + return 0; + } + return val_int_from_date(); +} + + +double Item_cache_temporal::val_real() +{ + DBUG_ASSERT(fixed == 1); + if ((!value_cached && !cache_value()) || null_value) + { + null_value= true; + return 0; + } + return val_real_from_date(); +} + + bool Item_cache_temporal::cache_value() { if (!example) diff --git a/sql/item.h b/sql/item.h index 084e77e4d23..03b333e7997 100644 --- a/sql/item.h +++ b/sql/item.h @@ -847,7 +847,9 @@ public: my_decimal *val_decimal_from_date(my_decimal *decimal_value); my_decimal *val_decimal_from_time(my_decimal *decimal_value); longlong val_int_from_decimal(); + longlong val_int_from_date(); double val_real_from_decimal(); + double val_real_from_date(); int save_time_in_field(Field *field); int save_date_in_field(Field *field); @@ -3830,6 +3832,10 @@ public: } String* val_str(String *str); + my_decimal *val_decimal(my_decimal *); + longlong val_int(); + longlong val_temporal_packed(); + double val_real(); bool cache_value(); bool get_date(MYSQL_TIME *ltime, uint fuzzydate); int save_in_field(Field *field, bool no_conversions); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 49e56a46e84..4817dadafd9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -877,10 +877,13 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, enum_field_types f_type= item->cmp_type() == TIME_RESULT ? item->field_type() : warn_item->field_type(); - if (item->result_type() == INT_RESULT && item->cmp_type() == TIME_RESULT) + if (item->result_type() == INT_RESULT && + item->cmp_type() == TIME_RESULT && + item->type() == Item::CACHE_ITEM) { - /* it's our Item_cache_int, as created below */ - value= item->val_int(); + /* it's our Item_cache_temporal, as created below */ + DBUG_ASSERT(is_temporal_type(((Item_cache *) item)->field_type())); + value= ((Item_cache_temporal*) item)->val_temporal_packed(); } else { diff --git a/sql/item_func.cc b/sql/item_func.cc index 9416d05cb2f..03cd6b5139d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -798,6 +798,8 @@ void Item_num_op::find_num_type(void) cached_result_type= DECIMAL_RESULT; result_precision(); fix_decimals(); + if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0) + cached_result_type= INT_RESULT; } else { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 489c0f1c23e..2d2001381a1 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -687,7 +687,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg) { - if (!(value= Item_cache::get_cache(item))) + if (!(value= Item_cache::get_cache(item, item->cmp_type()))) return; value->setup(item); value->store(value_arg); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index cb60368aafd..3baf583eaa0 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1362,27 +1362,6 @@ String *Item_temporal_func::val_str(String *str) } -longlong Item_temporal_func::val_int() -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_date(<ime, 0)) - return 0; - longlong v= TIME_to_ulonglong(<ime); - return ltime.neg ? -v : v; -} - - -double Item_temporal_func::val_real() -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_date(<ime, 0)) - return 0; - return TIME_to_double(<ime); -} - - bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date) { longlong value=args[0]->val_int(); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index bc048e1ff64..d97a5fbc903 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -448,8 +448,8 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } String *val_str(String *str); - longlong val_int(); - double val_real(); + longlong val_int() { return val_int_from_date(); } + double val_real() { return val_real_from_date(); } bool get_date(MYSQL_TIME *res, uint fuzzy_date) { DBUG_ASSERT(0); return 1; } my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } |