Skip to content

Commit cb2c799

Browse files
author
Alexander Barkov
committed
MDEV-8860 Wrong result for WHERE 2016 < SOME (SELECT CAST(time_column AS DATETIME) FROM t1)
MDEV-8875 Wrong metadata for MAX(CAST(time_column AS DATETIME))
1 parent cc9cfec commit cb2c799

File tree

6 files changed

+103
-18
lines changed

6 files changed

+103
-18
lines changed

mysql-test/r/func_time.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ select 1 from t1 where 1 < some (select cast(a as datetime) from t1);
17261726
1
17271727
1
17281728
Warnings:
1729-
Warning 1292 Truncated incorrect DOUBLE value: '2001-01-01 00:01:00'
1729+
Warning 1292 Incorrect datetime value: '1'
17301730
drop table t1;
17311731
SET timestamp=DEFAULT;
17321732
select time('10:10:10') > 10;

mysql-test/r/type_datetime.result

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,5 +1096,48 @@ Warnings:
10961096
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = TIMESTAMP'2001-01-01 00:00:00')
10971097
DROP TABLE t1;
10981098
#
1099+
# MDEV-8875 Wrong metadata for MAX(CAST(time_column AS DATETIME))
1100+
#
1101+
SET timestamp=UNIX_TIMESTAMP('2015-01-01 00:00:00');
1102+
CREATE TABLE t1 (a TIME);
1103+
INSERT INTO t1 VALUES ('00:00:00'),('00:01:00');
1104+
SELECT MAX(CAST(a AS DATETIME)) FROM t1;
1105+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
1106+
def MAX(CAST(a AS DATETIME)) 12 19 19 Y 128 0 63
1107+
MAX(CAST(a AS DATETIME))
1108+
2015-01-01 00:01:00
1109+
CREATE TABLE t2 AS SELECT MAX(CAST(a AS DATETIME)) FROM t1;
1110+
SHOW CREATE TABLE t2;
1111+
Table Create Table
1112+
t2 CREATE TABLE `t2` (
1113+
`MAX(CAST(a AS DATETIME))` datetime DEFAULT NULL
1114+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1115+
DROP TABLE t2;
1116+
DROP TABLE t1;
1117+
SET timestamp=DEFAULT;
1118+
#
1119+
# MDEV-8860 Wrong result for WHERE 2016 < SOME (SELECT CAST(time_column AS DATETIME) FROM t1)
1120+
#
1121+
SET timestamp=UNIX_TIMESTAMP('2015-01-01 00:00:00');
1122+
CREATE TABLE t1 (a TIME);
1123+
INSERT INTO t1 VALUES ('00:00:00'),('00:01:00');
1124+
SELECT 1 FROM t1 WHERE 2016 > SOME (SELECT CAST(a AS DATETIME) FROM t1);
1125+
1
1126+
Warnings:
1127+
Warning 1292 Incorrect datetime value: '2016'
1128+
SELECT * FROM t1 WHERE 2016 > CAST(a AS DATETIME);
1129+
a
1130+
Warnings:
1131+
Warning 1292 Incorrect datetime value: '2016'
1132+
SELECT 1 FROM t1 WHERE 20160101 > SOME (SELECT CAST(a AS DATETIME) FROM t1);
1133+
1
1134+
1
1135+
1
1136+
SELECT * FROM t1 WHERE 20160101 > CAST(a AS DATETIME);
1137+
a
1138+
00:00:00
1139+
00:01:00
1140+
DROP TABLE t1;
1141+
#
10991142
# End of 10.1 tests
11001143
#

mysql-test/t/type_datetime.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,35 @@ INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-02 00:00:00');
663663
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-01 00:00:00' AND COALESCE(a)>=TIMESTAMP'2001-01-01 00:00:00';
664664
DROP TABLE t1;
665665

666+
--echo #
667+
--echo # MDEV-8875 Wrong metadata for MAX(CAST(time_column AS DATETIME))
668+
--echo #
669+
SET timestamp=UNIX_TIMESTAMP('2015-01-01 00:00:00');
670+
CREATE TABLE t1 (a TIME);
671+
INSERT INTO t1 VALUES ('00:00:00'),('00:01:00');
672+
--disable_ps_protocol
673+
--enable_metadata
674+
SELECT MAX(CAST(a AS DATETIME)) FROM t1;
675+
--disable_metadata
676+
--enable_ps_protocol
677+
CREATE TABLE t2 AS SELECT MAX(CAST(a AS DATETIME)) FROM t1;
678+
SHOW CREATE TABLE t2;
679+
DROP TABLE t2;
680+
DROP TABLE t1;
681+
SET timestamp=DEFAULT;
682+
683+
--echo #
684+
--echo # MDEV-8860 Wrong result for WHERE 2016 < SOME (SELECT CAST(time_column AS DATETIME) FROM t1)
685+
--echo #
686+
SET timestamp=UNIX_TIMESTAMP('2015-01-01 00:00:00');
687+
CREATE TABLE t1 (a TIME);
688+
INSERT INTO t1 VALUES ('00:00:00'),('00:01:00');
689+
SELECT 1 FROM t1 WHERE 2016 > SOME (SELECT CAST(a AS DATETIME) FROM t1);
690+
SELECT * FROM t1 WHERE 2016 > CAST(a AS DATETIME);
691+
SELECT 1 FROM t1 WHERE 20160101 > SOME (SELECT CAST(a AS DATETIME) FROM t1);
692+
SELECT * FROM t1 WHERE 20160101 > CAST(a AS DATETIME);
693+
DROP TABLE t1;
694+
666695
--echo #
667696
--echo # End of 10.1 tests
668697
--echo #

sql/item_sum.cc

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,15 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
11901190
decimals=item->decimals;
11911191
with_subselect= args[0]->with_subselect;
11921192

1193-
switch (hybrid_type= item->result_type()) {
1193+
Item *item2= item->real_item();
1194+
if (item2->type() == Item::FIELD_ITEM)
1195+
set_handler_by_field_type(((Item_field*) item2)->field->type());
1196+
else if (item->cmp_type() == TIME_RESULT)
1197+
set_handler_by_field_type(item2->field_type());
1198+
else
1199+
set_handler_by_result_type(item2->result_type());
1200+
1201+
switch (Item_sum_hybrid::result_type()) {
11941202
case INT_RESULT:
11951203
case DECIMAL_RESULT:
11961204
case STRING_RESULT:
@@ -1210,11 +1218,6 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
12101218
result_field=0;
12111219
null_value=1;
12121220
fix_length_and_dec();
1213-
item= item->real_item();
1214-
if (item->type() == Item::FIELD_ITEM)
1215-
hybrid_field_type= ((Item_field*) item)->field->type();
1216-
else
1217-
hybrid_field_type= Item::field_type();
12181221

12191222
if (check_sum_func(thd, ref))
12201223
return TRUE;
@@ -2235,7 +2238,7 @@ void Item_sum_num::reset_field()
22352238

22362239
void Item_sum_hybrid::reset_field()
22372240
{
2238-
switch(hybrid_type) {
2241+
switch(Item_sum_hybrid::result_type()) {
22392242
case STRING_RESULT:
22402243
{
22412244
char buff[MAX_FIELD_WIDTH];
@@ -2507,7 +2510,7 @@ Item *Item_sum_avg::result_item(THD *thd, Field *field)
25072510

25082511
void Item_sum_hybrid::update_field()
25092512
{
2510-
switch (hybrid_type) {
2513+
switch (Item_sum_hybrid::result_type()) {
25112514
case STRING_RESULT:
25122515
min_max_update_str_field();
25132516
break;

sql/item_sum.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,26 +1027,26 @@ class Item_sum_std :public Item_sum_variance
10271027
// This class is a string or number function depending on num_func
10281028
class Arg_comparator;
10291029
class Item_cache;
1030-
class Item_sum_hybrid :public Item_sum
1030+
class Item_sum_hybrid :public Item_sum, public Type_handler_hybrid_field_type
10311031
{
10321032
protected:
10331033
Item_cache *value, *arg_cache;
10341034
Arg_comparator *cmp;
1035-
Item_result hybrid_type;
1036-
enum_field_types hybrid_field_type;
10371035
int cmp_sign;
10381036
bool was_values; // Set if we have found at least one row (for max/min only)
10391037
bool was_null_value;
10401038

10411039
public:
10421040
Item_sum_hybrid(THD *thd, Item *item_par,int sign):
1043-
Item_sum(thd, item_par), value(0), arg_cache(0), cmp(0),
1044-
hybrid_type(INT_RESULT), hybrid_field_type(MYSQL_TYPE_LONGLONG),
1041+
Item_sum(thd, item_par),
1042+
Type_handler_hybrid_field_type(MYSQL_TYPE_LONGLONG),
1043+
value(0), arg_cache(0), cmp(0),
10451044
cmp_sign(sign), was_values(TRUE)
10461045
{ collation.set(&my_charset_bin); }
10471046
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
1048-
:Item_sum(thd, item), value(item->value), arg_cache(0),
1049-
hybrid_type(item->hybrid_type), hybrid_field_type(item->hybrid_field_type),
1047+
:Item_sum(thd, item),
1048+
Type_handler_hybrid_field_type(item),
1049+
value(item->value), arg_cache(0),
10501050
cmp_sign(item->cmp_sign), was_values(item->was_values)
10511051
{ }
10521052
bool fix_fields(THD *, Item **);
@@ -1058,8 +1058,12 @@ class Item_sum_hybrid :public Item_sum
10581058
void reset_field();
10591059
String *val_str(String *);
10601060
bool keep_field_type(void) const { return 1; }
1061-
enum Item_result result_type () const { return hybrid_type; }
1062-
enum enum_field_types field_type() const { return hybrid_field_type; }
1061+
enum Item_result result_type () const
1062+
{ return Type_handler_hybrid_field_type::result_type(); }
1063+
enum Item_result cmp_type () const
1064+
{ return Type_handler_hybrid_field_type::cmp_type(); }
1065+
enum enum_field_types field_type() const
1066+
{ return Type_handler_hybrid_field_type::field_type(); }
10631067
void update_field();
10641068
void min_max_update_str_field();
10651069
void min_max_update_real_field();

sql/sql_type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ class Type_handler_hybrid_field_type: public Type_handler
270270
const Type_handler *get_handler_by_field_type(enum_field_types type) const;
271271
public:
272272
Type_handler_hybrid_field_type();
273+
Type_handler_hybrid_field_type(enum_field_types type)
274+
:m_type_handler(get_handler_by_field_type(type))
275+
{ }
276+
Type_handler_hybrid_field_type(const Type_handler_hybrid_field_type *other)
277+
:m_type_handler(other->m_type_handler)
278+
{ }
273279
enum_field_types field_type() const { return m_type_handler->field_type(); }
274280
Item_result result_type() const { return m_type_handler->result_type(); }
275281
Item_result cmp_type() const { return m_type_handler->cmp_type(); }

0 commit comments

Comments
 (0)