Commit 92499ae9 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-23320 Hex hybrid constants 0xHHHH work badly in rounding functions

- Type_handler_hex_hybrid did not override
  Type_handler_string_result::Item_func_round_fix_length_and_dec(),
  so the result type of ROUND(0xFFFFFFFFFFFFFFFF) was erroneously
  calculated ad DOUBLE with a wrong length.
  Overriding Item_func_round_fix_length_and_dec(), to calculated
  the result type as INT/BIGINT.

  Also, fixing Item_func_round::fix_arg_int() to use
  args[0]->decimal_precision() instead of args[0]->max_length
  when calculating this->max_length, to get a correct result
  for hex hybrids.

- Type_handler_hex_hybrid::Item_func_int_val_fix_length_and_dec()
  called item->fix_length_and_dec_int_or_decimal(), which did not
  produce a correct result data type for hex hybrid.
  Implementing a dedicated code instead, to return INT UNSIGNED or
  BIGINT UNSIGNED depending in the number of digits in the arguments.
parent 423de1e5
......@@ -20,5 +20,163 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(charset('a'))) + `test`.`t1`.`a` <=> <cache>(octet_length(charset(0x61))) + `test`.`t1`.`a`
DROP TABLE t1;
#
# MDEV-23320 Hex hybrid constants 0xHHHH work badly in rounding functions
#
BEGIN NOT ATOMIC
DECLARE arg TEXT DEFAULT '';
DECLARE query TEXT DEFAULT
'CREATE TABLE t1 AS SELECT '
'0xFFFFFFFFFFFFFFFF+0 AS c1,'
'FLOOR(0xFFFFFFFFFFFFFFFF) AS c2,'
'CEILING(0xFFFFFFFFFFFFFFFF) AS c3,'
'ROUND(0xFFFFFFFFFFFFFFFF) AS c4,'
'TRUNCATE(0xFFFFFFFFFFFFFFFF,0) AS c5';
FOR i IN 1..9
DO
SET arg= CONCAT('0x',REPEAT('FF',i));
SELECT i, arg;
EXECUTE IMMEDIATE REPLACE(query,'0xFFFFFFFFFFFFFFFF', arg);
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
END FOR;
END;
$$
i 1
arg 0xFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` int(4) unsigned NOT NULL,
`c2` int(3) unsigned NOT NULL,
`c3` int(3) unsigned NOT NULL,
`c4` int(3) unsigned NOT NULL,
`c5` int(3) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 255
c2 255
c3 255
c4 255
c5 255
i 2
arg 0xFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` int(6) unsigned NOT NULL,
`c2` int(5) unsigned NOT NULL,
`c3` int(5) unsigned NOT NULL,
`c4` int(5) unsigned NOT NULL,
`c5` int(5) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 65535
c2 65535
c3 65535
c4 65535
c5 65535
i 3
arg 0xFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` int(9) unsigned NOT NULL,
`c2` int(8) unsigned NOT NULL,
`c3` int(8) unsigned NOT NULL,
`c4` int(8) unsigned NOT NULL,
`c5` int(8) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 16777215
c2 16777215
c3 16777215
c4 16777215
c5 16777215
i 4
arg 0xFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(11) unsigned NOT NULL,
`c2` bigint(10) unsigned NOT NULL,
`c3` bigint(10) unsigned NOT NULL,
`c4` bigint(10) unsigned NOT NULL,
`c5` bigint(10) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 4294967295
c2 4294967295
c3 4294967295
c4 4294967295
c5 4294967295
i 5
arg 0xFFFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(14) unsigned NOT NULL,
`c2` bigint(13) unsigned NOT NULL,
`c3` bigint(13) unsigned NOT NULL,
`c4` bigint(13) unsigned NOT NULL,
`c5` bigint(13) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 1099511627775
c2 1099511627775
c3 1099511627775
c4 1099511627775
c5 1099511627775
i 6
arg 0xFFFFFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(16) unsigned NOT NULL,
`c2` bigint(15) unsigned NOT NULL,
`c3` bigint(15) unsigned NOT NULL,
`c4` bigint(15) unsigned NOT NULL,
`c5` bigint(15) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 281474976710655
c2 281474976710655
c3 281474976710655
c4 281474976710655
c5 281474976710655
i 7
arg 0xFFFFFFFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(18) unsigned NOT NULL,
`c2` bigint(17) unsigned NOT NULL,
`c3` bigint(17) unsigned NOT NULL,
`c4` bigint(17) unsigned NOT NULL,
`c5` bigint(17) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 72057594037927935
c2 72057594037927935
c3 72057594037927935
c4 72057594037927935
c5 72057594037927935
i 8
arg 0xFFFFFFFFFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(21) unsigned NOT NULL,
`c2` bigint(20) unsigned NOT NULL,
`c3` bigint(20) unsigned NOT NULL,
`c4` bigint(20) unsigned NOT NULL,
`c5` bigint(20) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 18446744073709551615
c2 18446744073709551615
c3 18446744073709551615
c4 18446744073709551615
c5 18446744073709551615
i 9
arg 0xFFFFFFFFFFFFFFFFFF
Table t1
Create Table CREATE TABLE `t1` (
`c1` bigint(21) unsigned NOT NULL,
`c2` bigint(20) unsigned NOT NULL,
`c3` bigint(20) unsigned NOT NULL,
`c4` bigint(20) unsigned NOT NULL,
`c5` bigint(20) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
c1 18446744073709551615
c2 18446744073709551615
c3 18446744073709551615
c4 18446744073709551615
c5 18446744073709551615
#
# End of 10.4 tests
#
......@@ -16,6 +16,36 @@ SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
DROP TABLE t1;
--echo #
--echo # MDEV-23320 Hex hybrid constants 0xHHHH work badly in rounding functions
--echo #
--vertical_results
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE arg TEXT DEFAULT '';
DECLARE query TEXT DEFAULT
'CREATE TABLE t1 AS SELECT '
'0xFFFFFFFFFFFFFFFF+0 AS c1,'
'FLOOR(0xFFFFFFFFFFFFFFFF) AS c2,'
'CEILING(0xFFFFFFFFFFFFFFFF) AS c3,'
'ROUND(0xFFFFFFFFFFFFFFFF) AS c4,'
'TRUNCATE(0xFFFFFFFFFFFFFFFF,0) AS c5';
FOR i IN 1..9
DO
SET arg= CONCAT('0x',REPEAT('FF',i));
SELECT i, arg;
EXECUTE IMMEDIATE REPLACE(query,'0xFFFFFFFFFFFFFFFF', arg);
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
END FOR;
END;
$$
DELIMITER ;$$
--horizontal_results
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -2228,6 +2228,7 @@ bool Item_func_int_val::fix_length_and_dec()
longlong Item_func_ceiling::int_op()
{
switch (args[0]->result_type()) {
case STRING_RESULT: // hex hybrid
case INT_RESULT:
return val_int_from_item(args[0]);
case DECIMAL_RESULT:
......@@ -2286,6 +2287,7 @@ bool Item_func_ceiling::time_op(THD *thd, MYSQL_TIME *to)
longlong Item_func_floor::int_op()
{
switch (args[0]->result_type()) {
case STRING_RESULT: // hex hybrid
case INT_RESULT:
return val_int_from_item(args[0]);
case DECIMAL_RESULT:
......@@ -2452,7 +2454,7 @@ void Item_func_round::fix_arg_int()
{
// Length can increase in some cases: ROUND(9,-1) -> 10
int length_can_increase= MY_TEST(!truncate && val1.neg());
max_length= args[0]->max_length + length_can_increase;
max_length= args[0]->decimal_precision() + length_can_increase;
// Here we can keep INT_RESULT
unsigned_flag= args[0]->unsigned_flag;
decimals= 0;
......
......@@ -5650,6 +5650,14 @@ bool Type_handler_int_result::
}
bool Type_handler_hex_hybrid::
Item_func_round_fix_length_and_dec(Item_func_round *item) const
{
item->fix_arg_int();
return false;
}
bool Type_handler_real_result::
Item_func_round_fix_length_and_dec(Item_func_round *item) const
{
......@@ -5743,7 +5751,14 @@ bool Type_handler_typelib::
bool Type_handler_hex_hybrid::
Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
{
item->fix_length_and_dec_int_or_decimal();
item->collation.set_numeric();
item->unsigned_flag= true;
item->max_length= item->arguments()[0]->decimal_precision();
#if MARIADB_VERSION_ID < 100500
item->set_handler(type_handler_long_or_longlong(item->max_length));
#else
item->set_handler(type_handler_long_or_longlong(item->max_length, true));
#endif
return false;
}
......
......@@ -6034,6 +6034,7 @@ class Type_handler_hex_hybrid: public Type_handler_varchar
const Name name() const { return m_name_hex_hybrid; }
const Type_handler *cast_to_int_type_handler() const;
const Type_handler *type_handler_for_system_time() const;
bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
};
......
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