summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mnogosearch.org>2013-11-21 11:46:36 +0400
committerAlexander Barkov <bar@mnogosearch.org>2013-11-21 11:46:36 +0400
commit2394fa67d4908f62ef14f3ca90269fb32806d193 (patch)
treef1b54751a653ab37af221f1b22a5368f5ee05ffc /sql
parentf8a6ee59acb082678cf601a10cbe9c1152748242 (diff)
downloadmariadb-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.cc69
-rw-r--r--sql/item.h6
-rw-r--r--sql/item_cmpfunc.cc9
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/item_timefunc.cc21
-rw-r--r--sql/item_timefunc.h4
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(&ltime, 0))
+ return 0;
+ longlong v= TIME_to_ulonglong(&ltime);
+ return ltime.neg ? -v : v;
+}
+
+
+double Item::val_real_from_date()
+{
+ DBUG_ASSERT(fixed == 1);
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, 0))
+ return 0;
+ return TIME_to_double(&ltime);
+}
+
+
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(&ltime, 0))
- return 0;
- longlong v= TIME_to_ulonglong(&ltime);
- return ltime.neg ? -v : v;
-}
-
-
-double Item_temporal_func::val_real()
-{
- DBUG_ASSERT(fixed == 1);
- MYSQL_TIME ltime;
- if (get_date(&ltime, 0))
- return 0;
- return TIME_to_double(&ltime);
-}
-
-
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); }