Commit eca207c4 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-25317 Assertion `scale <= precision' failed in decimal_bin_size And...

MDEV-25317 Assertion `scale <= precision' failed in decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision' failed in decimal_bin_size_inline/decimal_bin_size.

Precision should be kept below DECIMAL_MAX_SCALE for computations.
It can be bigger in Item_decimal. I'd fix this too but it changes the
existing behaviour so problemmatic to ix.
parent 945245ae
......@@ -989,6 +989,12 @@ ADDTIME('916:40:00', '416:40:00')
Warnings:
Warning 1292 Truncated incorrect time value: '916:40:00'
Warning 1292 Truncated incorrect time value: '1255:39:59.999999'
SELECT ADDTIME(20010101,1e0), ADDTIME(20010101,1.1e0);
ADDTIME(20010101,1e0) ADDTIME(20010101,1.1e0)
2001-01-01 00:00:01 2001-01-01 00:00:01.100000
SELECT ADDTIME(ADDTIME(20010101,1e0), 0);
ADDTIME(ADDTIME(20010101,1e0), 0)
2001-01-01 00:00:01
SELECT SUBTIME('916:40:00', '416:40:00');
SUBTIME('916:40:00', '416:40:00')
422:19:59.999999
......
......@@ -2456,5 +2456,29 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
#
# MDEV-25317 Assertion `scale <= precision' failed in
# decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision'
# failed in decimal_bin_size_inline/decimal_bin_size.
#
SELECT AVG(DISTINCT 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
AVG(DISTINCT 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0.00000000000000000000000000000000000000
CREATE TABLE t1 AS SELECT NULL AS v1;
SELECT 1 FROM t1 GROUP BY v1 ORDER BY AVG ( from_unixtime ( '' ) ) ;
1
1
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: ''
DROP TABLE t1;
SELECT SUM(DISTINCT 0.000000000000000000000000000000000000001);
SUM(DISTINCT 0.000000000000000000000000000000000000001)
0.00000000000000000000000000000000000000
CREATE TABLE t1 AS SELECT 1.000000000000000000000000000000000 AS a;
ALTER TABLE t1 ADD COLUMN b INT;
SELECT ROUND (a,b) AS c FROM t1 ORDER BY c;
c
NULL
DROP TABLE t1;
#
# End of 10.2 tests
#
......@@ -513,6 +513,10 @@ SELECT TIME_TO_SEC('916:40:00');
SELECT ADDTIME('500:00:00', '416:40:00');
SELECT ADDTIME('916:40:00', '416:40:00');
# check if ADDTIME() handles NOT_FIXED_DEC correctly
SELECT ADDTIME(20010101,1e0), ADDTIME(20010101,1.1e0);
SELECT ADDTIME(ADDTIME(20010101,1e0), 0);
# check if SUBTIME() handles out-of-range values correctly
SELECT SUBTIME('916:40:00', '416:40:00');
SELECT SUBTIME('-916:40:00', '416:40:00');
......
......@@ -1894,6 +1894,25 @@ show create table t1;
drop table t1;
--echo #
--echo # MDEV-25317 Assertion `scale <= precision' failed in
--echo # decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision'
--echo # failed in decimal_bin_size_inline/decimal_bin_size.
--echo #
SELECT AVG(DISTINCT 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
CREATE TABLE t1 AS SELECT NULL AS v1;
SELECT 1 FROM t1 GROUP BY v1 ORDER BY AVG ( from_unixtime ( '' ) ) ;
DROP TABLE t1;
SELECT SUM(DISTINCT 0.000000000000000000000000000000000000001);
CREATE TABLE t1 AS SELECT 1.000000000000000000000000000000000 AS a;
ALTER TABLE t1 ADD COLUMN b INT;
SELECT ROUND (a,b) AS c FROM t1 ORDER BY c;
DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #
......@@ -3103,6 +3103,15 @@ Field *Field_decimal::make_new_field(MEM_ROOT *root, TABLE *new_table,
}
void Field_new_decimal::set_and_validate_prec(uint32 len_arg,
uint8 dec_arg, bool unsigned_arg)
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
bin_size= my_decimal_get_binary_size(precision, dec);
}
/****************************************************************************
** Field_new_decimal
****************************************************************************/
......@@ -3115,13 +3124,10 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg,
uint8 dec_arg,bool zero_arg,
bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg)
unireg_check_arg, field_name_arg,
MY_MIN(dec_arg, DECIMAL_MAX_SCALE), zero_arg, unsigned_arg)
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
(dec <= DECIMAL_MAX_SCALE));
bin_size= my_decimal_get_binary_size(precision, dec);
set_and_validate_prec(len_arg, dec_arg, unsigned_arg);
}
......@@ -3132,13 +3138,11 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
bool unsigned_arg)
:Field_num((uchar*) 0, len_arg,
maybe_null_arg ? (uchar*) "": 0, 0,
NONE, name, dec_arg, 0, unsigned_arg)
NONE, name,
MY_MIN(dec_arg, DECIMAL_MAX_SCALE), 0, unsigned_arg)
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
(dec <= DECIMAL_MAX_SCALE));
bin_size= my_decimal_get_binary_size(precision, dec);
DBUG_ASSERT(dec <= DECIMAL_MAX_SCALE);
set_and_validate_prec(len_arg, dec_arg, unsigned_arg);
}
......
......@@ -1913,6 +1913,8 @@ class Field_decimal :public Field_real {
class Field_new_decimal :public Field_num {
private:
int do_save_field_metadata(uchar *first_byte);
void set_and_validate_prec(uint32 len_arg,
uint8 dec_arg, bool unsigned_arg);
public:
/* The maximum number of decimal digits can be stored */
uint precision;
......
......@@ -2453,14 +2453,16 @@ bool Item_func_round::fix_length_and_dec()
if (!args[1]->const_item())
{
decimals= args[0]->decimals;
max_length= float_length(decimals);
if (args[0]->result_type() == DECIMAL_RESULT)
{
max_length++;
max_length= args[0]->max_length;
set_handler_by_result_type(DECIMAL_RESULT);
}
else
{
max_length= float_length(decimals);
set_handler_by_result_type(REAL_RESULT);
}
return FALSE;
}
......
......@@ -1346,6 +1346,8 @@ bool Item_sum_sum::fix_length_and_dec()
{
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
decimals= MY_MIN(decimals, DECIMAL_MAX_SCALE);
precision= MY_MIN(precision, DECIMAL_MAX_PRECISION);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
......@@ -1673,12 +1675,12 @@ bool Item_sum_avg::fix_length_and_dec()
if (Item_sum_avg::result_type() == DECIMAL_RESULT)
{
int precision= args[0]->decimal_precision() + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
f_scale= args[0]->decimals;
f_scale= args[0]->decimal_scale();
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
}
else
......
......@@ -258,7 +258,6 @@ Type_handler_decimal_result::make_num_distinct_aggregator_field(
const Item *item)
const
{
DBUG_ASSERT(item->decimals <= DECIMAL_MAX_SCALE);
return new (mem_root)
Field_new_decimal(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
......
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