1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT

Bit operators (~ ^ | & << >>) and the function BIT_COUNT()
always called val_int() for their arguments.
It worked correctly only for INT type arguments.

In case of DECIMAL and DOUBLE arguments it did not work well:
the argument values were truncated to the maximum SIGNED BIGINT value
of 9223372036854775807.

Fixing the code as follows:

- If the argument if of an integer data type,
  it works using val_int() as before.

- If the argument if of some other data type, it gets the argument value
  using val_decimal(), to avoid truncation, and then converts the result
  to ulonglong.

Using Item_handled_func to switch between the two approaches easier.

As an additional advantage, with Item_handled_func it will be easier
to implement overloading in the future, so data type plugings will be able
to define their own behavioir of bit operators and BIT_COUNT().

Moving the code from the former val_int() implementations
as methods to Longlong_null, to avoid code duplication in the
INT and DECIMAL branches.
This commit is contained in:
Alexander Barkov
2020-06-05 12:57:42 +04:00
parent a793ae5bc1
commit 79cdd7e76b
12 changed files with 891 additions and 123 deletions

View File

@ -3071,7 +3071,7 @@ SELECT ((rpad(1.0,2048,1)) = ('4(') ^ (0.1));
((rpad(1.0,2048,1)) = ('4(') ^ (0.1))
0
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '4('
Warning 1292 Truncated incorrect DECIMAL value: '4('
SELECT
pow((rpad(10.0,2048,1)),(b'1111111111111111111111111111111111111111111'));
ERROR 22003: DOUBLE value is out of range in 'pow(rpad(10.0,2048,1),0x07ffffffffff)'
@ -3079,7 +3079,7 @@ SELECT ((rpad(1.0,2048,1)) + (0) ^ ('../'));
((rpad(1.0,2048,1)) + (0) ^ ('../'))
1.011111111111111
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '../'
Warning 1292 Truncated incorrect DECIMAL value: '../'
SELECT stddev_samp(rpad(1.0,2048,1));
stddev_samp(rpad(1.0,2048,1))
NULL