Skip to content

Commit 09b87d6

Browse files
author
Alexander Barkov
committed
MDEV-8871 Wrong result for CREATE TABLE .. SELECT LEAST(unsigned_column,unsigned_column)
1 parent c13f409 commit 09b87d6

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

mysql-test/r/func_test.result

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,5 +377,44 @@ id k c pad
377377
7 16 a xxx
378378
DROP TABLE t1;
379379
#
380+
# MDEV-8871 Wrong result for CREATE TABLE .. SELECT LEAST(unsigned_column,unsigned_column)
381+
#
382+
CREATE TABLE t1 (a INT,b INT UNSIGNED);
383+
INSERT INTO t1 VALUES (-2147483648,4294967295);
384+
SELECT a, b, LEAST(a,a), LEAST(b,b), LEAST(a,b), LEAST(b,a), GREATEST(a,b), GREATEST(b,a) FROM t1;
385+
a -2147483648
386+
b 4294967295
387+
LEAST(a,a) -2147483648
388+
LEAST(b,b) 4294967295
389+
LEAST(a,b) -2147483648
390+
LEAST(b,a) -2147483648
391+
GREATEST(a,b) 4294967295
392+
GREATEST(b,a) 4294967295
393+
CREATE TABLE t2 AS
394+
SELECT a, b, LEAST(a,a), LEAST(b,b), LEAST(a,b), LEAST(b,a), GREATEST(a,b), GREATEST(b,a) FROM t1;
395+
SHOW CREATE TABLE t2;
396+
Table Create Table
397+
t2 CREATE TABLE `t2` (
398+
`a` int(11) DEFAULT NULL,
399+
`b` int(10) unsigned DEFAULT NULL,
400+
`LEAST(a,a)` int(11) DEFAULT NULL,
401+
`LEAST(b,b)` int(10) unsigned DEFAULT NULL,
402+
`LEAST(a,b)` decimal(10,0) DEFAULT NULL,
403+
`LEAST(b,a)` decimal(10,0) DEFAULT NULL,
404+
`GREATEST(a,b)` decimal(10,0) DEFAULT NULL,
405+
`GREATEST(b,a)` decimal(10,0) DEFAULT NULL
406+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
407+
SELECT * FROM t2;
408+
a -2147483648
409+
b 4294967295
410+
LEAST(a,a) -2147483648
411+
LEAST(b,b) 4294967295
412+
LEAST(a,b) -2147483648
413+
LEAST(b,a) -2147483648
414+
GREATEST(a,b) 4294967295
415+
GREATEST(b,a) 4294967295
416+
DROP TABLE t2;
417+
DROP TABLE t1;
418+
#
380419
# End of 10.1 tests
381420
#

mysql-test/t/func_test.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,24 @@ SELECT * FROM t1 WHERE id XOR 0;
220220
SELECT * FROM t1 IGNORE KEY(PRIMARY) WHERE id XOR 0;
221221
DROP TABLE t1;
222222

223+
--echo #
224+
--echo # MDEV-8871 Wrong result for CREATE TABLE .. SELECT LEAST(unsigned_column,unsigned_column)
225+
--echo #
226+
CREATE TABLE t1 (a INT,b INT UNSIGNED);
227+
INSERT INTO t1 VALUES (-2147483648,4294967295);
228+
--vertical_results
229+
SELECT a, b, LEAST(a,a), LEAST(b,b), LEAST(a,b), LEAST(b,a), GREATEST(a,b), GREATEST(b,a) FROM t1;
230+
--horizontal_results
231+
CREATE TABLE t2 AS
232+
SELECT a, b, LEAST(a,a), LEAST(b,b), LEAST(a,b), LEAST(b,a), GREATEST(a,b), GREATEST(b,a) FROM t1;
233+
SHOW CREATE TABLE t2;
234+
--vertical_results
235+
SELECT * FROM t2;
236+
--horizontal_results
237+
DROP TABLE t2;
238+
DROP TABLE t1;
239+
240+
223241
--echo #
224242
--echo # End of 10.1 tests
225243
--echo #

sql/item_func.cc

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,26 +2823,48 @@ double Item_func_units::val_real()
28232823

28242824
void Item_func_min_max::fix_length_and_dec()
28252825
{
2826+
uint unsigned_count= 0;
28262827
int max_int_part=0;
28272828
decimals=0;
28282829
max_length=0;
28292830
maybe_null=0;
28302831
thd= current_thd;
2832+
compare_as_dates= find_date_time_item(args, arg_count, 0);
28312833
cmp_type=args[0]->result_type();
28322834

28332835
for (uint i=0 ; i < arg_count ; i++)
28342836
{
28352837
set_if_bigger(max_length, args[i]->max_length);
28362838
set_if_bigger(decimals, args[i]->decimals);
28372839
set_if_bigger(max_int_part, args[i]->decimal_int_part());
2840+
unsigned_count+= args[i]->unsigned_flag;
28382841
if (args[i]->maybe_null)
28392842
maybe_null= 1;
28402843
cmp_type= item_cmp_type(cmp_type,args[i]->result_type());
28412844
}
2845+
unsigned_flag= unsigned_count == arg_count; // if all args are unsigned
28422846
if (cmp_type == STRING_RESULT)
28432847
agg_arg_charsets_for_string_result_with_comparison(collation,
28442848
args, arg_count);
2845-
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
2849+
else if (cmp_type == INT_RESULT)
2850+
{
2851+
collation.set_numeric();
2852+
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
2853+
decimals,
2854+
decimals,
2855+
unsigned_flag));
2856+
if (unsigned_count != 0 && unsigned_count != arg_count)
2857+
{
2858+
/*
2859+
If all args are of INT-alike type, but have different unsigned_flag,
2860+
then change type to DECIMAL.
2861+
*/
2862+
cmp_type= DECIMAL_RESULT;
2863+
cached_field_type= MYSQL_TYPE_NEWDECIMAL;
2864+
return;
2865+
}
2866+
}
2867+
else if (cmp_type == DECIMAL_RESULT)
28462868
{
28472869
collation.set_numeric();
28482870
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
@@ -2853,7 +2875,6 @@ void Item_func_min_max::fix_length_and_dec()
28532875
else if (cmp_type == REAL_RESULT)
28542876
fix_char_length(float_length(decimals));
28552877

2856-
compare_as_dates= find_date_time_item(args, arg_count, 0);
28572878
if (compare_as_dates)
28582879
{
28592880
cached_field_type= compare_as_dates->field_type();

0 commit comments

Comments
 (0)