Commit 2394fa67 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-4859 Wrong value and data type of "SELECT MAX(time_column) + 1 FROM t1"

Fixed.
parent f8a6ee59
...@@ -958,10 +958,10 @@ sec_to_time(1) + 0, from_unixtime(1) + 0; ...@@ -958,10 +958,10 @@ sec_to_time(1) + 0, from_unixtime(1) + 0;
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`now() - now()` decimal(20,0) NOT NULL DEFAULT '0', `now() - now()` bigint(21) NOT NULL DEFAULT '0',
`curtime() - curtime()` decimal(11,0) NOT NULL DEFAULT '0', `curtime() - curtime()` bigint(12) NOT NULL DEFAULT '0',
`sec_to_time(1) + 0` decimal(11,0) DEFAULT NULL, `sec_to_time(1) + 0` bigint(12) DEFAULT NULL,
`from_unixtime(1) + 0` decimal(20,0) DEFAULT NULL `from_unixtime(1) + 0` bigint(21) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
SELECT SEC_TO_TIME(3300000); SELECT SEC_TO_TIME(3300000);
......
...@@ -191,5 +191,112 @@ SELECT CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00'))); ...@@ -191,5 +191,112 @@ SELECT CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00')));
CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00'))) CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00')))
768:00:01 768:00:01
# #
# MDEV-4859 Wrong value and data type of "SELECT MAX(time_column) + 1 FROM t1"
#
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1 FROM t1;
MAX(t0)+1
101011
CREATE TABLE t2 AS SELECT MAX(t0)+1 FROM t1;
SELECT * FROM t2;
MAX(t0)+1
101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1 bigint(12) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1.1 FROM t1;
MAX(t0)+1.1
101011.1
CREATE TABLE t2 AS SELECT MAX(t0)+1.1 FROM t1;
SELECT * FROM t2;
MAX(t0)+1.1
101011.1
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1.1 decimal(12,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1e0 FROM t1;
MAX(t0)+1e0
101011
CREATE TABLE t2 AS SELECT MAX(t0)+1e0 FROM t1;
SELECT * FROM t2;
MAX(t0)+1e0
101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1e0 double YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t1 TIME(1));
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t1)+1 FROM t1;
MAX(t1)+1
101011.0
CREATE TABLE t2 AS SELECT MAX(t1)+1 FROM t1;
SELECT * FROM t2;
MAX(t1)+1
101011.0
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t1)+1 decimal(13,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1 FROM t1;
MAX(t0)+1
20010101101011
CREATE TABLE t2 AS SELECT MAX(t0)+1 FROM t1;
SELECT * FROM t2;
MAX(t0)+1
20010101101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1 bigint(21) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1.1 FROM t1;
MAX(t0)+1.1
20010101101011.1
CREATE TABLE t2 AS SELECT MAX(t0)+1.1 FROM t1;
SELECT * FROM t2;
MAX(t0)+1.1
20010101101011.1
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1.1 decimal(21,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1e0 FROM t1;
MAX(t0)+1e0
20010101101011
CREATE TABLE t2 AS SELECT MAX(t0)+1e0 FROM t1;
SELECT * FROM t2;
MAX(t0)+1e0
20010101101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t0)+1e0 double YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t1 DATETIME(1));
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t1)+1 FROM t1;
MAX(t1)+1
20010101101011.0
CREATE TABLE t2 AS SELECT MAX(t1)+1 FROM t1;
SELECT * FROM t2;
MAX(t1)+1
20010101101011.0
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
MAX(t1)+1 decimal(22,1) YES NULL
DROP TABLE t2,t1;
#
# End of 5.3 tests # End of 5.3 tests
# #
...@@ -134,6 +134,74 @@ SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5'); ...@@ -134,6 +134,74 @@ SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5');
SELECT CONCAT(GREATEST(TIME('00:00:01'),TIME('00:00:00'))); SELECT CONCAT(GREATEST(TIME('00:00:01'),TIME('00:00:00')));
SELECT CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00'))); SELECT CONCAT(GREATEST(TIME('32 00:00:01'),TIME('00:00:00')));
--echo #
--echo # MDEV-4859 Wrong value and data type of "SELECT MAX(time_column) + 1 FROM t1"
--echo #
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1.1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1.1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t0)+1e0 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1e0 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t1 TIME(1));
INSERT INTO t1 VALUES ('10:10:10');
SELECT MAX(t1)+1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t1)+1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1.1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1.1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t0)+1e0 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t0)+1e0 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
CREATE TABLE t1 (t1 DATETIME(1));
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
SELECT MAX(t1)+1 FROM t1;
CREATE TABLE t2 AS SELECT MAX(t1)+1 FROM t1;
SELECT * FROM t2;
SHOW COLUMNS FROM t2;
DROP TABLE t2,t1;
--echo # --echo #
--echo # End of 5.3 tests --echo # End of 5.3 tests
--echo # --echo #
...@@ -350,6 +350,27 @@ my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) ...@@ -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() double Item::val_real_from_decimal()
{ {
/* Note that fix_fields may not be called for Item_avg_field items */ /* 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) ...@@ -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) String *Item_cache_temporal::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
...@@ -8393,6 +8426,42 @@ String *Item_cache_temporal::val_str(String *str) ...@@ -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() bool Item_cache_temporal::cache_value()
{ {
if (!example) if (!example)
......
...@@ -847,7 +847,9 @@ class Item { ...@@ -847,7 +847,9 @@ class Item {
my_decimal *val_decimal_from_date(my_decimal *decimal_value); my_decimal *val_decimal_from_date(my_decimal *decimal_value);
my_decimal *val_decimal_from_time(my_decimal *decimal_value); my_decimal *val_decimal_from_time(my_decimal *decimal_value);
longlong val_int_from_decimal(); longlong val_int_from_decimal();
longlong val_int_from_date();
double val_real_from_decimal(); double val_real_from_decimal();
double val_real_from_date();
int save_time_in_field(Field *field); int save_time_in_field(Field *field);
int save_date_in_field(Field *field); int save_date_in_field(Field *field);
...@@ -3830,6 +3832,10 @@ class Item_cache_temporal: public Item_cache_int ...@@ -3830,6 +3832,10 @@ class Item_cache_temporal: public Item_cache_int
} }
String* val_str(String *str); 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 cache_value();
bool get_date(MYSQL_TIME *ltime, uint fuzzydate); bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
......
...@@ -877,10 +877,13 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, ...@@ -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 ? enum_field_types f_type= item->cmp_type() == TIME_RESULT ?
item->field_type() : warn_item->field_type(); 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 */ /* it's our Item_cache_temporal, as created below */
value= item->val_int(); DBUG_ASSERT(is_temporal_type(((Item_cache *) item)->field_type()));
value= ((Item_cache_temporal*) item)->val_temporal_packed();
} }
else else
{ {
......
...@@ -798,6 +798,8 @@ void Item_num_op::find_num_type(void) ...@@ -798,6 +798,8 @@ void Item_num_op::find_num_type(void)
cached_result_type= DECIMAL_RESULT; cached_result_type= DECIMAL_RESULT;
result_precision(); result_precision();
fix_decimals(); fix_decimals();
if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
cached_result_type= INT_RESULT;
} }
else else
{ {
......
...@@ -687,7 +687,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) ...@@ -687,7 +687,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg) 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; return;
value->setup(item); value->setup(item);
value->store(value_arg); value->store(value_arg);
......
...@@ -1362,27 +1362,6 @@ String *Item_temporal_func::val_str(String *str) ...@@ -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) bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
{ {
longlong value=args[0]->val_int(); longlong value=args[0]->val_int();
......
...@@ -448,8 +448,8 @@ class Item_temporal_func: public Item_func ...@@ -448,8 +448,8 @@ class Item_temporal_func: public Item_func
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
String *val_str(String *str); String *val_str(String *str);
longlong val_int(); longlong val_int() { return val_int_from_date(); }
double val_real(); double val_real() { return val_real_from_date(); }
bool get_date(MYSQL_TIME *res, uint fuzzy_date) { DBUG_ASSERT(0); return 1; } bool get_date(MYSQL_TIME *res, uint fuzzy_date) { DBUG_ASSERT(0); return 1; }
my_decimal *val_decimal(my_decimal *decimal_value) my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); } { return val_decimal_from_date(decimal_value); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment