1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +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

@ -338,6 +338,10 @@ public:
double to_double() const { return m_ptr ? m_ptr->to_double() : 0.0; }
longlong to_longlong(bool unsigned_flag)
{ return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; }
Longlong_null to_xlonglong_null()
{
return m_ptr ? Longlong_null(m_ptr->to_xlonglong()) : Longlong_null();
}
bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; }
String *to_string(String *to) const
{