mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
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
This commit is contained in:
@@ -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 coalesce_a_b 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_______b_a 12 10 19 Y 128 0 63
|
||||
def ifnull___a_b 12 10 19 Y 128 0 63
|
||||
def ifnull___b_a 12 10 19 Y 128 0 63
|
||||
def if_______a_b 12 19 19 Y 128 0 63
|
||||
def if_______b_a 12 19 19 Y 128 0 63
|
||||
def ifnull___a_b 12 19 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____b_a 12 10 19 Y 128 0 63
|
||||
def greatest_a_b 12 10 19 Y 128 0 63
|
||||
@@ -3396,5 +3396,36 @@ c1
|
||||
DROP TABLE t2;
|
||||
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
|
||||
#
|
||||
|
||||
@@ -1220,3 +1220,31 @@ Warning 1292 Truncated incorrect DOUBLE value: '1E+'
|
||||
#
|
||||
# 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;
|
||||
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 # End of 10.1 tests
|
||||
--echo #
|
||||
|
||||
@@ -681,3 +681,27 @@ SELECT
|
||||
--echo #
|
||||
--echo # End of 10.0 tests
|
||||
--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)
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
int arg0_int_part= args[0]->decimal_int_part();
|
||||
@@ -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
|
||||
THD::change_item_tree() if needed.
|
||||
@@ -3155,18 +3093,7 @@ void Item_func_case::fix_length_and_dec()
|
||||
}
|
||||
else
|
||||
{
|
||||
collation.set_numeric();
|
||||
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);
|
||||
fix_attributes(agg, nagg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -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_func_coalesce::result_type()) {
|
||||
switch (Item_hybrid_func::result_type()) {
|
||||
case STRING_RESULT:
|
||||
if (count_string_result_length(Item_func_coalesce::field_type(),
|
||||
args, arg_count))
|
||||
if (count_string_result_length(Item_hybrid_func::field_type(),
|
||||
items, nitems))
|
||||
return;
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
count_decimal_length();
|
||||
collation.set_numeric();
|
||||
count_decimal_length(items, nitems);
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
count_real_length();
|
||||
collation.set_numeric();
|
||||
count_real_length(items, nitems);
|
||||
break;
|
||||
case INT_RESULT:
|
||||
count_only_length(args, arg_count);
|
||||
collation.set_numeric();
|
||||
count_only_length(items, nitems);
|
||||
decimals= 0;
|
||||
break;
|
||||
case ROW_RESULT:
|
||||
|
||||
@@ -902,7 +902,11 @@ public:
|
||||
String *str_op(String *);
|
||||
my_decimal *decimal_op(my_decimal *);
|
||||
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"; }
|
||||
table_map not_null_tables() const { return 0; }
|
||||
};
|
||||
@@ -915,13 +919,18 @@ public:
|
||||
*/
|
||||
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:
|
||||
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
|
||||
Item_func_hybrid_field_type(thd, a, b) { }
|
||||
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *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 @@ public:
|
||||
Item *find_item(String *str);
|
||||
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -612,18 +612,19 @@ void Item_udf_func::fix_num_length_and_dec()
|
||||
|
||||
@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;
|
||||
decimals= 0;
|
||||
if (field_type() != MYSQL_TYPE_DATE)
|
||||
if (field_type_arg != MYSQL_TYPE_DATE)
|
||||
{
|
||||
for (uint i= 0; i < nitems; i++)
|
||||
set_if_bigger(decimals, item[i]->decimals);
|
||||
}
|
||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -632,16 +633,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems)
|
||||
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;
|
||||
decimals= 0;
|
||||
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(max_int_part, args[i]->decimal_int_part());
|
||||
set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
|
||||
set_if_bigger(decimals, item[i]->decimals);
|
||||
set_if_bigger(max_int_part, item[i]->decimal_int_part());
|
||||
set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
|
||||
}
|
||||
int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_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)
|
||||
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;
|
||||
decimals= 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)
|
||||
{
|
||||
set_if_bigger(decimals, args[i]->decimals);
|
||||
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
|
||||
set_if_bigger(decimals, items[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)
|
||||
{
|
||||
@@ -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))
|
||||
return true;
|
||||
if (is_temporal_type(field_type_arg))
|
||||
count_datetime_length(items, nitems);
|
||||
count_datetime_length(field_type_arg, items, nitems);
|
||||
else
|
||||
{
|
||||
decimals= NOT_FIXED_DEC;
|
||||
count_only_length(items, nitems);
|
||||
decimals= max_length ? NOT_FIXED_DEC : 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -792,7 +794,7 @@ void Item_num_op::fix_length_and_dec(void)
|
||||
if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
|
||||
r0 == STRING_RESULT || r1 ==STRING_RESULT)
|
||||
{
|
||||
count_real_length();
|
||||
count_real_length(args, arg_count);
|
||||
max_length= float_length(decimals);
|
||||
set_handler_by_result_type(REAL_RESULT);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,14 @@ protected:
|
||||
*/
|
||||
uint allowed_arg_cols;
|
||||
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:
|
||||
table_map not_null_tables_cache;
|
||||
|
||||
@@ -148,16 +156,10 @@ public:
|
||||
virtual void print(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 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
null_value= args[0]->get_time(ltime);
|
||||
@@ -387,6 +389,8 @@ public:
|
||||
class Item_hybrid_func: public Item_func,
|
||||
public Type_handler_hybrid_field_type
|
||||
{
|
||||
protected:
|
||||
void fix_attributes(Item **item, uint nitems);
|
||||
public:
|
||||
Item_hybrid_func(THD *thd): Item_func(thd) { }
|
||||
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
|
||||
|
||||
Reference in New Issue
Block a user