[MCOL-4651] SEC_TO_TIME(hugePositiveDecimal) returns a negative time Created: 2021-03-30  Updated: 2021-03-30  Resolved: 2021-03-30

Status: Closed
Project: MariaDB ColumnStore
Component/s: PrimProc
Affects Version/s: 5.6.1, 6.1.1
Fix Version/s: 6.1.1

Type: Bug Priority: Major
Reporter: Alexander Barkov Assignee: Alexander Barkov
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Blocks
blocks MCOL-4361 Replace pow(10.0, (double)scale) expr... Closed
Relates
relates to MCOL-4607 SEC_TO_TIME(wideDecimal) returns 0 in... Open
relates to MCOL-4623 sec_to_time() does not support FLOAT/... Open
relates to MCOL-4647 SEC_TO_TIME(double_or_float) returns ... Closed

 Description   

DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a DECIMAL(30,1)) ENGINE=ColumnStore;
INSERT INTO t1 VALUES (9223372036854775807.0);
INSERT INTO t1 VALUES (9223372036854775807.5);
INSERT INTO t1 VALUES (18446744073709551615.0);
INSERT INTO t1 VALUES (18446744073709551615.5);
SELECT a, SEC_TO_TIME(a) FROM t1 ORDER BY a;

+------------------------+----------------+
| a                      | SEC_TO_TIME(a) |
+------------------------+----------------+
|  9223372036854775807.0 | 838:59:59.0    |
|  9223372036854775807.5 | -838:59:59.0   | -- bad
| 18446744073709551615.0 | 838:59:59.0    |
| 18446744073709551615.5 | -838:59:59.0   | -- bad
+------------------------+----------------+

Looks wrong. The correct result is:

DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a DECIMAL(30,1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (9223372036854775807.0);
INSERT INTO t1 VALUES (9223372036854775807.5);
INSERT INTO t1 VALUES (18446744073709551615.0);
INSERT INTO t1 VALUES (18446744073709551615.5);
SELECT a, SEC_TO_TIME(a) FROM t1 ORDER BY a;

+------------------------+----------------+
| a                      | SEC_TO_TIME(a) |
+------------------------+----------------+
|  9223372036854775807.0 | 838:59:59.9    |
|  9223372036854775807.5 | 838:59:59.9    |
| 18446744073709551615.0 | 838:59:59.9    |
| 18446744073709551615.5 | 838:59:59.9    |
+------------------------+----------------+

Note, the microsecond value is zero in MCS because of MCOL-4608.
But at least the integer part should be fixed not to return negative values.

The problem reside in Func_sec_to_time::getStrVal():

        case execplan::CalpontSystemCatalog::DECIMAL:
        case execplan::CalpontSystemCatalog::UDECIMAL:
        {
            const string& valStr = parm[0]->data()->getStrVal(row, isNull);
 
            val = parm[0]->data()->getIntVal(row, isNull);
            size_t x = valStr.find(".");
 
            if (x < string::npos)
            {
                string tmp = valStr.substr(x + 1, 1);
                char* ptr = &tmp[0];
                int i = atoi(ptr);
 
                if (i >= 5)
                {
                    if (val > 0)
                        val += 1;
                    else
                        val -= 1;
                }
            }
        }
        break;

The above code performs rounding without checking the range properly. So a huge positive integer, e.g. 9223372036854775807 wraps around to a negative value.


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