[MCOL-5568] Columnstore query returns incorrect value instead of expected out-of-range error Created: 2023-09-06  Updated: 2023-12-21  Resolved: 2023-12-14

Status: Closed
Project: MariaDB ColumnStore
Component/s: None
Affects Version/s: 6.4.6, 22.08.8
Fix Version/s: 23.10.1

Type: Bug Priority: Major
Reporter: Edward Stoever Assignee: Sergey Zefirov
Resolution: Fixed Votes: 1
Labels: rm_invalid_data, triage

Sprint: 2023-11
Assigned for Review: Roman Roman
Assigned for Testing: Kirill Perov Kirill Perov

 Description   

create schema coltest; use coltest;
drop table if exists test_mult;
create table test_mult (
indemnity_paid int(11),
n_clms tinyint(3) unsigned
) engine=columnstore;
insert into test_mult (indemnity_paid, n_clms) values (-10, 1);
select indemnity_paid, n_clms, indemnity_paid * n_clms from test_mult;
+----------------+--------+-------------------------+
| indemnity_paid | n_clms | indemnity_paid * n_clms |
+----------------+--------+-------------------------+
|            -10 |      1 |    18446744073709551606 |
+----------------+--------+-------------------------+

The multiplication produces an incorrect value.
For the same table defined engine=innodb, the multiplication produces an expected out-of-range error:

alter table test_mult engine=innodb;
select indemnity_paid, n_clms, indemnity_paid * n_clms from test_mult;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '`coltest`.`test_mult`.`indemnity_paid` * `coltest`.`test_mult`.`n_clms`'



 Comments   
Comment by Roman [ 2023-09-22 ]

MDB promotes the mult type into UNSIGNED BIGINT however their mult processing checks if the signed column value is negative or not. If it is there is an error that is propagated upwards. MCS math processing lacks error propagation.

Comment by Leonid Fedorov [ 2023-09-22 ]

BTW query can be rewritten
<code>
MariaDB [coltest]> select indemnity_paid, n_clms, indemnity_paid * cast(n_clms as signed) from test_mult;
-------------------------------------------------------------

indemnity_paid n_clms indemnity_paid * cast(n_clms as signed)

-------------------------------------------------------------

-10 1 -10

-------------------------------------------------------------
1 row in set (0.012 sec)
<code>

Comment by Roman [ 2023-09-23 ]

Here are some comments on how does type coercion happens in MDB/MySQL:

```
If both operands are integers and any of them are unsigned, the result is an unsigned integer. For subtraction, if the NO_UNSIGNED_SUBTRACTION SQL mode is enabled, the result is signed even if any operand is unsigned.
```
There is another important aspect of this issue. There is a JIT patch almost ready to be merged. This patch is affected by the fact MCS doesn't do overflow or value domain checks like we see in this issue when negative int64 value is bit-casted into uint64. This upcoming change must be also taken into account.
I suggest we search for similar issues filed previously by Bar. If not we should file an umbrella ticket to copy MDB behavior doing math with numerics.

Comment by Kirill Perov [ 2023-11-01 ]

sergey.zefirov,drrtuy

1.
select indemnity_paid, n_clms, indemnity_paid / n_clms from test_mult;

---------------------------------------------

indemnity_paid n_clms indemnity_paid / n_clms

---------------------------------------------

-10 1 -10.0000

---------------------------------------------
1 row in set (0.019 sec)

I have expected it should give error according to: "If both operands are integers and any of them are unsigned, the result is an unsigned integer." But both MCS and MDB shows -10 as result here.

2. In non strict mode if out-of-range value is inserted and truncated, MDB shows 1 warning:
Warning (Code 1264): Out of range value for column 'n_clms' at row 1

and MCS shows 2 warnings
Warning (Code 1264): Out of range value for column 'n_clms' at row 1
Warning (Code 1264): CAL0001: MCS-2025: Data truncated for column 'n_clms'

3. For DECIMAL UNSIGNED, FLOAT UNSIGNED and DOUBLE UNSIGNED both MDB and MCS shows -10 as result, no error.

Comment by Roman [ 2023-11-02 ]

Right, integer operands division produces float.

Could you elaborate on whether integer division actually truncates for the 2nd scenario in your prev comment kirill.perov@mariadb.com?

Comment by Kirill Perov [ 2023-11-02 ]

drrtuy Second scenario was about insertion of values > 256 into tinyint unsigned column.
For division:

MariaDB [coltest]> select indemnity_paid, n_clms, indemnity_paid / n_clms from test_mult;
---------------------------------------------

indemnity_paid n_clms indemnity_paid / n_clms

---------------------------------------------

-10 1 -10.0000
-10 253 -0.0395

---------------------------------------------
2 rows in set (0.009 sec)

No errors or warnings there.

Comment by Kirill Perov [ 2023-11-15 ]

testing finished ok

Generated at Thu Feb 08 02:58:50 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.