Skip to content

Commit 16ad1fc

Browse files
author
Alexander Barkov
committed
MDEV-8921 Wrong result for CAST(AVG(double_column) AS SIGNED)
1 parent 7091b78 commit 16ad1fc

File tree

6 files changed

+44
-15
lines changed

6 files changed

+44
-15
lines changed

mysql-test/r/func_group.result

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,5 +2298,21 @@ id avg cast_avg
22982298
2 9223372036854775807.0000 9223372036854775807
22992299
DROP TABLE t1;
23002300
#
2301+
# MDEV-8921 Wrong result for CAST(AVG(double_column) AS SIGNED)
2302+
#
2303+
CREATE TABLE t1 (id INT, a DOUBLE);
2304+
INSERT INTO t1 VALUES (1,0x7FFFFFFFFFFFFFFF),(2,0x7FFFFFFFFFFFFFFF);
2305+
SELECT id, AVG(a) AS avg, CAST(MIN(a) AS SIGNED) AS cast_min,CAST(AVG(a) AS SIGNED) AS cast_avg FROM t1 GROUP BY id HAVING avg!=123 ORDER BY id;
2306+
id avg cast_min cast_avg
2307+
1 9.223372036854776e18 9223372036854775807 9223372036854775807
2308+
2 9.223372036854776e18 9223372036854775807 9223372036854775807
2309+
DROP TABLE t1;
2310+
CREATE TABLE t1 (a DOUBLE);
2311+
INSERT INTO t1 VALUES (0x7FFFFFFFFFFFFFFF);
2312+
SELECT MIN(a), SUM(a), CAST(SUM(a) AS SIGNED), CAST(AVG(a) AS SIGNED) FROM t1;
2313+
MIN(a) SUM(a) CAST(SUM(a) AS SIGNED) CAST(AVG(a) AS SIGNED)
2314+
9.223372036854776e18 9.223372036854776e18 9223372036854775807 9223372036854775807
2315+
DROP TABLE t1;
2316+
#
23012317
# End of 10.1 tests
23022318
#

mysql-test/t/func_group.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,18 @@ SELECT id, AVG(a) AS avg, CAST(MIN(a) AS SIGNED) AS cast_min FROM t1 GROUP BY id
15811581
SELECT id, AVG(a) AS avg, CAST(AVG(a) AS SIGNED) AS cast_avg FROM t1 GROUP BY id HAVING avg!=123 ORDER BY id;
15821582
DROP TABLE t1;
15831583

1584+
--echo #
1585+
--echo # MDEV-8921 Wrong result for CAST(AVG(double_column) AS SIGNED)
1586+
--echo #
1587+
CREATE TABLE t1 (id INT, a DOUBLE);
1588+
INSERT INTO t1 VALUES (1,0x7FFFFFFFFFFFFFFF),(2,0x7FFFFFFFFFFFFFFF);
1589+
SELECT id, AVG(a) AS avg, CAST(MIN(a) AS SIGNED) AS cast_min,CAST(AVG(a) AS SIGNED) AS cast_avg FROM t1 GROUP BY id HAVING avg!=123 ORDER BY id;
1590+
DROP TABLE t1;
1591+
CREATE TABLE t1 (a DOUBLE);
1592+
INSERT INTO t1 VALUES (0x7FFFFFFFFFFFFFFF);
1593+
SELECT MIN(a), SUM(a), CAST(SUM(a) AS SIGNED), CAST(AVG(a) AS SIGNED) FROM t1;
1594+
DROP TABLE t1;
1595+
15841596
--echo #
15851597
--echo # End of 10.1 tests
15861598
--echo #

sql/item.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,14 @@ longlong Item::val_int_from_date()
359359
}
360360

361361

362+
longlong Item::val_int_from_real()
363+
{
364+
DBUG_ASSERT(fixed == 1);
365+
bool error;
366+
return double_to_longlong(val_real(), false /*unsigned_flag*/, &error);
367+
}
368+
369+
362370
double Item::val_real_from_date()
363371
{
364372
DBUG_ASSERT(fixed == 1);

sql/item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,7 @@ class Item: public Value_source,
10081008
my_decimal *val_decimal_from_time(my_decimal *decimal_value);
10091009
longlong val_int_from_decimal();
10101010
longlong val_int_from_date();
1011+
longlong val_int_from_real();
10111012
double val_real_from_decimal();
10121013
double val_real_from_date();
10131014

sql/item_sum.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@ longlong Item_sum_sum::val_int()
14301430
&result);
14311431
return result;
14321432
}
1433-
return (longlong) rint(val_real());
1433+
return val_int_from_real();
14341434
}
14351435

14361436

sql/item_sum.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -704,11 +704,7 @@ class Item_sum_num :public Item_sum
704704
Item_sum_num(THD *thd, Item_sum_num *item):
705705
Item_sum(thd, item),is_evaluated(item->is_evaluated) {}
706706
bool fix_fields(THD *, Item **);
707-
longlong val_int()
708-
{
709-
DBUG_ASSERT(fixed == 1);
710-
return (longlong) rint(val_real()); /* Real as default */
711-
}
707+
longlong val_int() { return val_int_from_real(); /* Real as default */ }
712708
String *val_str(String*str);
713709
my_decimal *val_decimal(my_decimal *);
714710
void reset_field();
@@ -843,7 +839,7 @@ class Item_sum_avg :public Item_sum_sum
843839
bool add();
844840
double val_real();
845841
// In SPs we might force the "wrong" type with select into a declare variable
846-
longlong val_int() { return (longlong) rint(val_real()); }
842+
longlong val_int() { return val_int_from_real(); }
847843
my_decimal *val_decimal(my_decimal *);
848844
String *val_str(String *str);
849845
void reset_field();
@@ -1093,6 +1089,7 @@ class Item_sum_field :public Item
10931089
decimals= item->decimals;
10941090
max_length= item->max_length;
10951091
unsigned_flag= item->unsigned_flag;
1092+
fixed= true;
10961093
}
10971094
table_map used_tables() const { return (table_map) 1L; }
10981095
Field *get_tmp_table_field() { DBUG_ASSERT(0); return NULL; }
@@ -1127,7 +1124,7 @@ class Item_avg_field_double :public Item_avg_field
11271124
{ }
11281125
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
11291126
enum Item_result result_type () const { return REAL_RESULT; }
1130-
longlong val_int() { return (longlong) rint(val_real()); }
1127+
longlong val_int() { return val_int_from_real(); }
11311128
my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_real(dec); }
11321129
String *val_str(String *str) { return val_string_from_real(str); }
11331130
double val_real();
@@ -1162,8 +1159,7 @@ class Item_variance_field :public Item_sum_field
11621159
{ }
11631160
enum Type type() const {return FIELD_VARIANCE_ITEM; }
11641161
double val_real();
1165-
longlong val_int()
1166-
{ /* can't be fix_fields()ed */ return (longlong) rint(val_real()); }
1162+
longlong val_int() { return val_int_from_real(); }
11671163
String *val_str(String *str)
11681164
{ return val_string_from_real(str); }
11691165
my_decimal *val_decimal(my_decimal *dec_buf)
@@ -1246,11 +1242,7 @@ class Item_sum_udf_float :public Item_udf_sum
12461242
Item_udf_sum(thd, udf_arg, list) {}
12471243
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
12481244
:Item_udf_sum(thd, item) {}
1249-
longlong val_int()
1250-
{
1251-
DBUG_ASSERT(fixed == 1);
1252-
return (longlong) rint(Item_sum_udf_float::val_real());
1253-
}
1245+
longlong val_int() { return val_int_from_real(); }
12541246
double val_real();
12551247
String *val_str(String*str);
12561248
my_decimal *val_decimal(my_decimal *);

0 commit comments

Comments
 (0)