Details
- 
    Bug 
- 
    Status: Closed (View Workflow)
- 
    Major 
- 
    Resolution: Fixed
- 
    5.6.1, 6.1.1
- 
    None
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.
Attachments
Issue Links
- blocks
- 
                    MCOL-4361 Replace pow(10.0, (double)scale) expressions with a static dictionary lookup. -         
- Closed
 
-