Commit b25373be authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9653 Assertion `length || !scale' failed in uint...

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
parent 546e9139
...@@ -2175,10 +2175,10 @@ def case_____a_b 12 19 19 Y 128 0 63 ...@@ -2175,10 +2175,10 @@ def case_____a_b 12 19 19 Y 128 0 63
def case_____b_a 12 19 19 Y 128 0 63 def case_____b_a 12 19 19 Y 128 0 63
def coalesce_a_b 12 19 19 Y 128 0 63 def coalesce_a_b 12 19 19 Y 128 0 63
def coalesce_b_a 12 19 19 Y 128 0 63 def coalesce_b_a 12 19 19 Y 128 0 63
def if_______a_b 12 10 19 Y 128 0 63 def if_______a_b 12 19 19 Y 128 0 63
def if_______b_a 12 10 19 Y 128 0 63 def if_______b_a 12 19 19 Y 128 0 63
def ifnull___a_b 12 10 19 Y 128 0 63 def ifnull___a_b 12 19 19 Y 128 0 63
def ifnull___b_a 12 10 19 Y 128 0 63 def ifnull___b_a 12 19 19 Y 128 0 63
def least____a_b 12 10 19 Y 128 0 63 def least____a_b 12 10 19 Y 128 0 63
def least____b_a 12 10 19 Y 128 0 63 def least____b_a 12 10 19 Y 128 0 63
def greatest_a_b 12 10 19 Y 128 0 63 def greatest_a_b 12 10 19 Y 128 0 63
...@@ -3396,5 +3396,36 @@ c1 ...@@ -3396,5 +3396,36 @@ c1
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
#
SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END
NULL
SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END
NULL
SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END
NULL
SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c0 246 4 3 Y 32896 1 63
def c1 246 4 3 Y 32896 1 63
c0 c1
1.1 1.1
#
# MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements
#
PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b";
SET @a=1;
EXECUTE stmt USING @a,@a;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(21) DEFAULT NULL,
`b` varchar(21) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.1 tests # End of 10.1 tests
# #
...@@ -1220,3 +1220,31 @@ Warning 1292 Truncated incorrect DOUBLE value: '1E+' ...@@ -1220,3 +1220,31 @@ Warning 1292 Truncated incorrect DOUBLE value: '1E+'
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
#
SELECT NULL+1 AS c0,
COALESCE(NULL)+1 AS c2,
COALESCE(COALESCE(NULL))+1 AS c3,
''+1 AS c4,
COALESCE('')+1 AS c5,
COALESCE(COALESCE(''))+1 AS c6;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c0 5 17 0 Y 32896 0 63
def c2 5 17 0 Y 32896 0 63
def c3 5 17 0 Y 32896 0 63
def c4 5 23 1 N 32897 31 63
def c5 5 17 1 N 32897 0 63
def c6 5 17 1 N 32897 0 63
c0 c2 c3 c4 c5 c6
NULL NULL NULL 1 1 1
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: ''
Warning 1292 Truncated incorrect DOUBLE value: ''
Warning 1292 Truncated incorrect DOUBLE value: ''
#
# Start of 10.1 tests
#
...@@ -433,6 +433,29 @@ DROP TABLE t2; ...@@ -433,6 +433,29 @@ DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
--echo #
SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
--disable_ps_protocol
--enable_metadata
SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1;
--disable_metadata
--enable_ps_protocol
--echo #
--echo # MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements
--echo #
PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b";
SET @a=1;
EXECUTE stmt USING @a,@a;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #
...@@ -681,3 +681,27 @@ SELECT ...@@ -681,3 +681,27 @@ SELECT
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
--echo #
--disable_ps_protocol
--enable_metadata
SELECT NULL+1 AS c0,
COALESCE(NULL)+1 AS c2,
COALESCE(COALESCE(NULL))+1 AS c3,
''+1 AS c4,
COALESCE('')+1 AS c5,
COALESCE(COALESCE(''))+1 AS c6;
--disable_metadata
--enable_ps_protocol
--echo #
--echo # Start of 10.1 tests
--echo #
...@@ -2246,50 +2246,6 @@ void Item_func_between::print(String *str, enum_query_type query_type) ...@@ -2246,50 +2246,6 @@ void Item_func_between::print(String *str, enum_query_type query_type)
} }
void
Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
{
uint32 char_length;
set_handler_by_field_type(agg_field_type(args, 2, true));
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
if (Item_func_case_abbreviation2::result_type() == DECIMAL_RESULT ||
Item_func_case_abbreviation2::result_type() == INT_RESULT)
{
int len0= args[0]->max_char_length() - args[0]->decimals
- (args[0]->unsigned_flag ? 0 : 1);
int len1= args[1]->max_char_length() - args[1]->decimals
- (args[1]->unsigned_flag ? 0 : 1);
char_length= MY_MAX(len0, len1) + decimals + (unsigned_flag ? 0 : 1);
}
else
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
switch (Item_func_case_abbreviation2::result_type()) {
case STRING_RESULT:
if (count_string_result_length(Item_func_case_abbreviation2::field_type(),
args, 2))
return;
break;
case DECIMAL_RESULT:
case REAL_RESULT:
break;
case INT_RESULT:
decimals= 0;
break;
case ROW_RESULT:
case TIME_RESULT:
DBUG_ASSERT(0);
}
fix_char_length(char_length);
}
uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const
{ {
int arg0_int_part= args[0]->decimal_int_part(); int arg0_int_part= args[0]->decimal_int_part();
...@@ -3076,24 +3032,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) ...@@ -3076,24 +3032,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
} }
void Item_func_case::agg_str_lengths(Item* arg)
{
fix_char_length(MY_MAX(max_char_length(), arg->max_char_length()));
set_if_bigger(decimals, arg->decimals);
unsigned_flag= unsigned_flag && arg->unsigned_flag;
}
void Item_func_case::agg_num_lengths(Item *arg)
{
uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals,
arg->unsigned_flag) - arg->decimals;
set_if_bigger(max_length, len);
set_if_bigger(decimals, arg->decimals);
unsigned_flag= unsigned_flag && arg->unsigned_flag;
}
/** /**
Check if (*place) and new_value points to different Items and call Check if (*place) and new_value points to different Items and call
THD::change_item_tree() if needed. THD::change_item_tree() if needed.
...@@ -3155,18 +3093,7 @@ void Item_func_case::fix_length_and_dec() ...@@ -3155,18 +3093,7 @@ void Item_func_case::fix_length_and_dec()
} }
else else
{ {
collation.set_numeric(); fix_attributes(agg, nagg);
max_length=0;
decimals=0;
unsigned_flag= TRUE;
for (uint i= 0; i < ncases; i+= 2)
agg_num_lengths(args[i + 1]);
if (else_expr_num != -1)
agg_num_lengths(args[else_expr_num]);
max_length= my_decimal_precision_to_length_no_truncation(max_length +
decimals,
decimals,
unsigned_flag);
} }
/* /*
...@@ -3468,23 +3395,25 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) ...@@ -3468,23 +3395,25 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
} }
void Item_func_coalesce::fix_length_and_dec() void Item_hybrid_func::fix_attributes(Item **items, uint nitems)
{ {
set_handler_by_field_type(agg_field_type(args, arg_count, true)); switch (Item_hybrid_func::result_type()) {
switch (Item_func_coalesce::result_type()) {
case STRING_RESULT: case STRING_RESULT:
if (count_string_result_length(Item_func_coalesce::field_type(), if (count_string_result_length(Item_hybrid_func::field_type(),
args, arg_count)) items, nitems))
return; return;
break; break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
count_decimal_length(); collation.set_numeric();
count_decimal_length(items, nitems);
break; break;
case REAL_RESULT: case REAL_RESULT:
count_real_length(); collation.set_numeric();
count_real_length(items, nitems);
break; break;
case INT_RESULT: case INT_RESULT:
count_only_length(args, arg_count); collation.set_numeric();
count_only_length(items, nitems);
decimals= 0; decimals= 0;
break; break;
case ROW_RESULT: case ROW_RESULT:
......
...@@ -902,7 +902,11 @@ class Item_func_coalesce :public Item_func_hybrid_field_type ...@@ -902,7 +902,11 @@ class Item_func_coalesce :public Item_func_hybrid_field_type
String *str_op(String *); String *str_op(String *);
my_decimal *decimal_op(my_decimal *); my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime,uint fuzzydate); bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec(); void fix_length_and_dec()
{
set_handler_by_field_type(agg_field_type(args, arg_count, true));
fix_attributes(args, arg_count);
}
const char *func_name() const { return "coalesce"; } const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
}; };
...@@ -915,13 +919,18 @@ class Item_func_coalesce :public Item_func_hybrid_field_type ...@@ -915,13 +919,18 @@ class Item_func_coalesce :public Item_func_hybrid_field_type
*/ */
class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
{ {
protected:
void fix_length_and_dec2(Item **items)
{
set_handler_by_field_type(agg_field_type(items, 2, true));
fix_attributes(items, 2);
}
uint decimal_precision2(Item **args) const;
public: public:
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b): Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
Item_func_hybrid_field_type(thd, a, b) { } Item_func_hybrid_field_type(thd, a, b) { }
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c): Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c):
Item_func_hybrid_field_type(thd, a, b, c) { } Item_func_hybrid_field_type(thd, a, b, c) { }
void fix_length_and_dec2(Item **args);
uint decimal_precision2(Item **args) const;
}; };
...@@ -1454,8 +1463,6 @@ class Item_func_case :public Item_func_hybrid_field_type ...@@ -1454,8 +1463,6 @@ class Item_func_case :public Item_func_hybrid_field_type
Item *find_item(String *str); Item *find_item(String *str);
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
void cleanup(); void cleanup();
void agg_str_lengths(Item *arg);
void agg_num_lengths(Item *arg);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond); Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
}; };
......
...@@ -612,18 +612,19 @@ void Item_udf_func::fix_num_length_and_dec() ...@@ -612,18 +612,19 @@ void Item_udf_func::fix_num_length_and_dec()
@retval False on success, true on error. @retval False on success, true on error.
*/ */
void Item_func::count_datetime_length(Item **item, uint nitems) void Item_func::count_datetime_length(enum_field_types field_type_arg,
Item **item, uint nitems)
{ {
unsigned_flag= 0; unsigned_flag= 0;
decimals= 0; decimals= 0;
if (field_type() != MYSQL_TYPE_DATE) if (field_type_arg != MYSQL_TYPE_DATE)
{ {
for (uint i= 0; i < nitems; i++) for (uint i= 0; i < nitems; i++)
set_if_bigger(decimals, item[i]->decimals); set_if_bigger(decimals, item[i]->decimals);
} }
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
uint len= decimals ? (decimals + 1) : 0; uint len= decimals ? (decimals + 1) : 0;
len+= mysql_temporal_int_part_length(field_type()); len+= mysql_temporal_int_part_length(field_type_arg);
fix_char_length(len); fix_char_length(len);
} }
...@@ -632,16 +633,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems) ...@@ -632,16 +633,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems)
result length/precision depends on argument ones. result length/precision depends on argument ones.
*/ */
void Item_func::count_decimal_length() void Item_func::count_decimal_length(Item **item, uint nitems)
{ {
int max_int_part= 0; int max_int_part= 0;
decimals= 0; decimals= 0;
unsigned_flag= 1; unsigned_flag= 1;
for (uint i=0 ; i < arg_count ; i++) for (uint i=0 ; i < nitems ; i++)
{ {
set_if_bigger(decimals, args[i]->decimals); set_if_bigger(decimals, item[i]->decimals);
set_if_bigger(max_int_part, args[i]->decimal_int_part()); set_if_bigger(max_int_part, item[i]->decimal_int_part());
set_if_smaller(unsigned_flag, args[i]->unsigned_flag); set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
} }
int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION); int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
fix_char_length(my_decimal_precision_to_length_no_truncation(precision, fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
...@@ -672,19 +673,20 @@ void Item_func::count_only_length(Item **item, uint nitems) ...@@ -672,19 +673,20 @@ void Item_func::count_only_length(Item **item, uint nitems)
result length/precision depends on argument ones. result length/precision depends on argument ones.
*/ */
void Item_func::count_real_length() void Item_func::count_real_length(Item **items, uint nitems)
{ {
uint32 length= 0; uint32 length= 0;
decimals= 0; decimals= 0;
max_length= 0; max_length= 0;
for (uint i=0 ; i < arg_count ; i++) unsigned_flag= false;
for (uint i=0 ; i < nitems ; i++)
{ {
if (decimals != NOT_FIXED_DEC) if (decimals != NOT_FIXED_DEC)
{ {
set_if_bigger(decimals, args[i]->decimals); set_if_bigger(decimals, items[i]->decimals);
set_if_bigger(length, (args[i]->max_length - args[i]->decimals)); set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
} }
set_if_bigger(max_length, args[i]->max_length); set_if_bigger(max_length, items[i]->max_length);
} }
if (decimals != NOT_FIXED_DEC) if (decimals != NOT_FIXED_DEC)
{ {
...@@ -713,11 +715,11 @@ bool Item_func::count_string_result_length(enum_field_types field_type_arg, ...@@ -713,11 +715,11 @@ bool Item_func::count_string_result_length(enum_field_types field_type_arg,
if (agg_arg_charsets_for_string_result(collation, items, nitems, 1)) if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
return true; return true;
if (is_temporal_type(field_type_arg)) if (is_temporal_type(field_type_arg))
count_datetime_length(items, nitems); count_datetime_length(field_type_arg, items, nitems);
else else
{ {
decimals= NOT_FIXED_DEC;
count_only_length(items, nitems); count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0;
} }
return false; return false;
} }
...@@ -792,7 +794,7 @@ void Item_num_op::fix_length_and_dec(void) ...@@ -792,7 +794,7 @@ void Item_num_op::fix_length_and_dec(void)
if (r0 == REAL_RESULT || r1 == REAL_RESULT || if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
r0 == STRING_RESULT || r1 ==STRING_RESULT) r0 == STRING_RESULT || r1 ==STRING_RESULT)
{ {
count_real_length(); count_real_length(args, arg_count);
max_length= float_length(decimals); max_length= float_length(decimals);
set_handler_by_result_type(REAL_RESULT); set_handler_by_result_type(REAL_RESULT);
} }
......
...@@ -41,6 +41,14 @@ class Item_func :public Item_func_or_sum ...@@ -41,6 +41,14 @@ class Item_func :public Item_func_or_sum
*/ */
uint allowed_arg_cols; uint allowed_arg_cols;
String *val_str_from_val_str_ascii(String *str, String *str2); String *val_str_from_val_str_ascii(String *str, String *str2);
void count_only_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems);
void count_datetime_length(enum_field_types field_type,
Item **item, uint nitems);
bool count_string_result_length(enum_field_types field_type,
Item **item, uint nitems);
public: public:
table_map not_null_tables_cache; table_map not_null_tables_cache;
...@@ -148,16 +156,10 @@ class Item_func :public Item_func_or_sum ...@@ -148,16 +156,10 @@ class Item_func :public Item_func_or_sum
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
void print_op(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type);
void print_args(String *str, uint from, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type);
void count_only_length(Item **item, uint nitems);
void count_real_length();
void count_decimal_length();
inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{ {
return (null_value=args[0]->get_date_with_conversion(ltime, fuzzy_date)); return (null_value=args[0]->get_date_with_conversion(ltime, fuzzy_date));
} }
void count_datetime_length(Item **item, uint nitems);
bool count_string_result_length(enum_field_types field_type,
Item **item, uint nitems);
inline bool get_arg0_time(MYSQL_TIME *ltime) inline bool get_arg0_time(MYSQL_TIME *ltime)
{ {
null_value= args[0]->get_time(ltime); null_value= args[0]->get_time(ltime);
...@@ -387,6 +389,8 @@ class Item_real_func :public Item_func ...@@ -387,6 +389,8 @@ class Item_real_func :public Item_func
class Item_hybrid_func: public Item_func, class Item_hybrid_func: public Item_func,
public Type_handler_hybrid_field_type public Type_handler_hybrid_field_type
{ {
protected:
void fix_attributes(Item **item, uint nitems);
public: public:
Item_hybrid_func(THD *thd): Item_func(thd) { } Item_hybrid_func(THD *thd): Item_func(thd) { }
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { } Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
......
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