Skip to content

Commit b25373b

Browse files
author
Alexander Barkov
committed
MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements
1 parent 546e913 commit b25373b

File tree

8 files changed

+161
-113
lines changed

8 files changed

+161
-113
lines changed

mysql-test/r/func_hybrid_type.result

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,10 +2175,10 @@ def case_____a_b 12 19 19 Y 128 0 63
21752175
def case_____b_a 12 19 19 Y 128 0 63
21762176
def coalesce_a_b 12 19 19 Y 128 0 63
21772177
def coalesce_b_a 12 19 19 Y 128 0 63
2178-
def if_______a_b 12 10 19 Y 128 0 63
2179-
def if_______b_a 12 10 19 Y 128 0 63
2180-
def ifnull___a_b 12 10 19 Y 128 0 63
2181-
def ifnull___b_a 12 10 19 Y 128 0 63
2178+
def if_______a_b 12 19 19 Y 128 0 63
2179+
def if_______b_a 12 19 19 Y 128 0 63
2180+
def ifnull___a_b 12 19 19 Y 128 0 63
2181+
def ifnull___b_a 12 19 19 Y 128 0 63
21822182
def least____a_b 12 10 19 Y 128 0 63
21832183
def least____b_a 12 10 19 Y 128 0 63
21842184
def greatest_a_b 12 10 19 Y 128 0 63
@@ -3396,5 +3396,36 @@ c1
33963396
DROP TABLE t2;
33973397
DROP TABLE t1;
33983398
#
3399+
# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
3400+
#
3401+
SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
3402+
CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END
3403+
NULL
3404+
SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
3405+
CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END
3406+
NULL
3407+
SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
3408+
CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END
3409+
NULL
3410+
SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1;
3411+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
3412+
def c0 246 4 3 Y 32896 1 63
3413+
def c1 246 4 3 Y 32896 1 63
3414+
c0 c1
3415+
1.1 1.1
3416+
#
3417+
# MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements
3418+
#
3419+
PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b";
3420+
SET @a=1;
3421+
EXECUTE stmt USING @a,@a;
3422+
SHOW CREATE TABLE t1;
3423+
Table Create Table
3424+
t1 CREATE TABLE `t1` (
3425+
`a` varchar(21) DEFAULT NULL,
3426+
`b` varchar(21) DEFAULT NULL
3427+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
3428+
DROP TABLE t1;
3429+
#
33993430
# End of 10.1 tests
34003431
#

mysql-test/r/type_num.result

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,3 +1220,31 @@ Warning 1292 Truncated incorrect DOUBLE value: '1E+'
12201220
#
12211221
# End of 10.0 tests
12221222
#
1223+
#
1224+
# Start of 10.1 tests
1225+
#
1226+
#
1227+
# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
1228+
#
1229+
SELECT NULL+1 AS c0,
1230+
COALESCE(NULL)+1 AS c2,
1231+
COALESCE(COALESCE(NULL))+1 AS c3,
1232+
''+1 AS c4,
1233+
COALESCE('')+1 AS c5,
1234+
COALESCE(COALESCE(''))+1 AS c6;
1235+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
1236+
def c0 5 17 0 Y 32896 0 63
1237+
def c2 5 17 0 Y 32896 0 63
1238+
def c3 5 17 0 Y 32896 0 63
1239+
def c4 5 23 1 N 32897 31 63
1240+
def c5 5 17 1 N 32897 0 63
1241+
def c6 5 17 1 N 32897 0 63
1242+
c0 c2 c3 c4 c5 c6
1243+
NULL NULL NULL 1 1 1
1244+
Warnings:
1245+
Warning 1292 Truncated incorrect DOUBLE value: ''
1246+
Warning 1292 Truncated incorrect DOUBLE value: ''
1247+
Warning 1292 Truncated incorrect DOUBLE value: ''
1248+
#
1249+
# Start of 10.1 tests
1250+
#

mysql-test/t/func_hybrid_type.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,29 @@ DROP TABLE t2;
433433
DROP TABLE t1;
434434

435435

436+
--echo #
437+
--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
438+
--echo #
439+
SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
440+
SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
441+
SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
442+
443+
--disable_ps_protocol
444+
--enable_metadata
445+
SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1;
446+
--disable_metadata
447+
--enable_ps_protocol
448+
449+
450+
--echo #
451+
--echo # MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements
452+
--echo #
453+
PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b";
454+
SET @a=1;
455+
EXECUTE stmt USING @a,@a;
456+
SHOW CREATE TABLE t1;
457+
DROP TABLE t1;
458+
436459
--echo #
437460
--echo # End of 10.1 tests
438461
--echo #

mysql-test/t/type_num.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,3 +681,27 @@ SELECT
681681
--echo #
682682
--echo # End of 10.0 tests
683683
--echo #
684+
685+
--echo #
686+
--echo # Start of 10.1 tests
687+
--echo #
688+
689+
--echo #
690+
--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
691+
--echo #
692+
693+
--disable_ps_protocol
694+
--enable_metadata
695+
SELECT NULL+1 AS c0,
696+
COALESCE(NULL)+1 AS c2,
697+
COALESCE(COALESCE(NULL))+1 AS c3,
698+
''+1 AS c4,
699+
COALESCE('')+1 AS c5,
700+
COALESCE(COALESCE(''))+1 AS c6;
701+
--disable_metadata
702+
--enable_ps_protocol
703+
704+
705+
--echo #
706+
--echo # Start of 10.1 tests
707+
--echo #

sql/item_cmpfunc.cc

Lines changed: 11 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,50 +2246,6 @@ void Item_func_between::print(String *str, enum_query_type query_type)
22462246
}
22472247

22482248

2249-
void
2250-
Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
2251-
{
2252-
uint32 char_length;
2253-
set_handler_by_field_type(agg_field_type(args, 2, true));
2254-
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
2255-
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
2256-
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
2257-
2258-
if (Item_func_case_abbreviation2::result_type() == DECIMAL_RESULT ||
2259-
Item_func_case_abbreviation2::result_type() == INT_RESULT)
2260-
{
2261-
int len0= args[0]->max_char_length() - args[0]->decimals
2262-
- (args[0]->unsigned_flag ? 0 : 1);
2263-
2264-
int len1= args[1]->max_char_length() - args[1]->decimals
2265-
- (args[1]->unsigned_flag ? 0 : 1);
2266-
2267-
char_length= MY_MAX(len0, len1) + decimals + (unsigned_flag ? 0 : 1);
2268-
}
2269-
else
2270-
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
2271-
2272-
switch (Item_func_case_abbreviation2::result_type()) {
2273-
case STRING_RESULT:
2274-
if (count_string_result_length(Item_func_case_abbreviation2::field_type(),
2275-
args, 2))
2276-
return;
2277-
break;
2278-
case DECIMAL_RESULT:
2279-
case REAL_RESULT:
2280-
break;
2281-
case INT_RESULT:
2282-
decimals= 0;
2283-
break;
2284-
case ROW_RESULT:
2285-
case TIME_RESULT:
2286-
DBUG_ASSERT(0);
2287-
}
2288-
fix_char_length(char_length);
2289-
}
2290-
2291-
2292-
22932249
uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const
22942250
{
22952251
int arg0_int_part= args[0]->decimal_int_part();
@@ -3076,24 +3032,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
30763032
}
30773033

30783034

3079-
void Item_func_case::agg_str_lengths(Item* arg)
3080-
{
3081-
fix_char_length(MY_MAX(max_char_length(), arg->max_char_length()));
3082-
set_if_bigger(decimals, arg->decimals);
3083-
unsigned_flag= unsigned_flag && arg->unsigned_flag;
3084-
}
3085-
3086-
3087-
void Item_func_case::agg_num_lengths(Item *arg)
3088-
{
3089-
uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals,
3090-
arg->unsigned_flag) - arg->decimals;
3091-
set_if_bigger(max_length, len);
3092-
set_if_bigger(decimals, arg->decimals);
3093-
unsigned_flag= unsigned_flag && arg->unsigned_flag;
3094-
}
3095-
3096-
30973035
/**
30983036
Check if (*place) and new_value points to different Items and call
30993037
THD::change_item_tree() if needed.
@@ -3155,18 +3093,7 @@ void Item_func_case::fix_length_and_dec()
31553093
}
31563094
else
31573095
{
3158-
collation.set_numeric();
3159-
max_length=0;
3160-
decimals=0;
3161-
unsigned_flag= TRUE;
3162-
for (uint i= 0; i < ncases; i+= 2)
3163-
agg_num_lengths(args[i + 1]);
3164-
if (else_expr_num != -1)
3165-
agg_num_lengths(args[else_expr_num]);
3166-
max_length= my_decimal_precision_to_length_no_truncation(max_length +
3167-
decimals,
3168-
decimals,
3169-
unsigned_flag);
3096+
fix_attributes(agg, nagg);
31703097
}
31713098

31723099
/*
@@ -3468,23 +3395,25 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
34683395
}
34693396

34703397

3471-
void Item_func_coalesce::fix_length_and_dec()
3398+
void Item_hybrid_func::fix_attributes(Item **items, uint nitems)
34723399
{
3473-
set_handler_by_field_type(agg_field_type(args, arg_count, true));
3474-
switch (Item_func_coalesce::result_type()) {
3400+
switch (Item_hybrid_func::result_type()) {
34753401
case STRING_RESULT:
3476-
if (count_string_result_length(Item_func_coalesce::field_type(),
3477-
args, arg_count))
3402+
if (count_string_result_length(Item_hybrid_func::field_type(),
3403+
items, nitems))
34783404
return;
34793405
break;
34803406
case DECIMAL_RESULT:
3481-
count_decimal_length();
3407+
collation.set_numeric();
3408+
count_decimal_length(items, nitems);
34823409
break;
34833410
case REAL_RESULT:
3484-
count_real_length();
3411+
collation.set_numeric();
3412+
count_real_length(items, nitems);
34853413
break;
34863414
case INT_RESULT:
3487-
count_only_length(args, arg_count);
3415+
collation.set_numeric();
3416+
count_only_length(items, nitems);
34883417
decimals= 0;
34893418
break;
34903419
case ROW_RESULT:

sql/item_cmpfunc.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,11 @@ class Item_func_coalesce :public Item_func_hybrid_field_type
902902
String *str_op(String *);
903903
my_decimal *decimal_op(my_decimal *);
904904
bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
905-
void fix_length_and_dec();
905+
void fix_length_and_dec()
906+
{
907+
set_handler_by_field_type(agg_field_type(args, arg_count, true));
908+
fix_attributes(args, arg_count);
909+
}
906910
const char *func_name() const { return "coalesce"; }
907911
table_map not_null_tables() const { return 0; }
908912
};
@@ -915,13 +919,18 @@ class Item_func_coalesce :public Item_func_hybrid_field_type
915919
*/
916920
class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
917921
{
922+
protected:
923+
void fix_length_and_dec2(Item **items)
924+
{
925+
set_handler_by_field_type(agg_field_type(items, 2, true));
926+
fix_attributes(items, 2);
927+
}
928+
uint decimal_precision2(Item **args) const;
918929
public:
919930
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
920931
Item_func_hybrid_field_type(thd, a, b) { }
921932
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c):
922933
Item_func_hybrid_field_type(thd, a, b, c) { }
923-
void fix_length_and_dec2(Item **args);
924-
uint decimal_precision2(Item **args) const;
925934
};
926935

927936

@@ -1454,8 +1463,6 @@ class Item_func_case :public Item_func_hybrid_field_type
14541463
Item *find_item(String *str);
14551464
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
14561465
void cleanup();
1457-
void agg_str_lengths(Item *arg);
1458-
void agg_num_lengths(Item *arg);
14591466
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
14601467
};
14611468

0 commit comments

Comments
 (0)