diff --git a/dbcon/execplan/arithmeticoperator.h b/dbcon/execplan/arithmeticoperator.h index e694e577e..33e4dfc15 100644 --- a/dbcon/execplan/arithmeticoperator.h +++ b/dbcon/execplan/arithmeticoperator.h @@ -31,6 +31,7 @@ #include "operator.h" #include "parsetree.h" +#include "mcs_datatype.h" namespace messageqcpp { @@ -238,6 +239,51 @@ inline void ArithmeticOperator::evaluate(rowgroup::Row& row, bool& isNull, Parse break; case execplan::CalpontSystemCatalog::UBIGINT: + { + // XXX: this is bandaid solution for specific customer case (MCOL-5568). + // Despite that I tried to implement a proper solution: to have operations + // performed using int128_t amd then check the result. + int128_t x, y; + bool signedLeft = lop->data()->resultType().isSignedInteger(); + bool signedRight = rop->data()->resultType().isSignedInteger(); + if (signedLeft) + { + x = static_cast(lop->getIntVal(row, isNull)); + } + else + { + x = static_cast(lop->getUintVal(row, isNull)); + } + if (signedRight) + { + y = static_cast(rop->getIntVal(row, isNull)); + } + else + { + y = static_cast(rop->getUintVal(row, isNull)); + } + int128_t result = execute(x, y, isNull); + if (!isNull && (result > MAX_UBIGINT || result < 0)) + { + logging::Message::Args args; + std::string func = ""; + switch (fOp) + { + case OP_ADD: func = "\"+\""; break; + case OP_SUB: func = "\"-\""; break; + case OP_MUL: func = "\"*\""; break; + case OP_DIV: func = "\"/\""; break; + default: break; + } + args.add(func); + args.add(static_cast(x)); + args.add(static_cast(y)); + unsigned errcode = logging::ERR_FUNC_OUT_OF_RANGE_RESULT; + throw logging::IDBExcept(logging::IDBErrorInfo::instance()->errorMsg(errcode, args), errcode); + } + fResult.uintVal = static_castdata() && (sfitempp[1]->type() == Item::FUNC_ITEM)) diff --git a/mysql-test/columnstore/basic/r/MCOL-5568-out-of-range.result b/mysql-test/columnstore/basic/r/MCOL-5568-out-of-range.result new file mode 100644 index 000000000..f00a81d3d --- /dev/null +++ b/mysql-test/columnstore/basic/r/MCOL-5568-out-of-range.result @@ -0,0 +1,61 @@ +DROP DATABASE IF EXISTS MCOL5568; +CREATE DATABASE MCOL5568; +USE MCOL5568; +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; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "*" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "+" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult; +indemnity_paid n_clms (indemnity_paid + 9) + n_clms +-10 1 0 +CREATE TABLE test_mult2 ( +indemnity_paid TINYINT, +n_clms TINYINT UNSIGNED +) ENGINE=COLUMNSTORE; +INSERT INTO test_mult2 (indemnity_paid, n_clms) VALUES (-10, 1); +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult2; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "*" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult2; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "+" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult2; +indemnity_paid n_clms (indemnity_paid + 9) + n_clms +-10 1 0 +CREATE TABLE test_mult3 ( +indemnity_paid SMALLINT, +n_clms TINYINT UNSIGNED +) ENGINE=COLUMNSTORE; +INSERT INTO test_mult3 (indemnity_paid, n_clms) VALUES (-10, 1); +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult3; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "*" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult3; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "+" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult3; +indemnity_paid n_clms (indemnity_paid + 9) + n_clms +-10 1 0 +CREATE TABLE test_mult4 ( +indemnity_paid INTEGER, +n_clms TINYINT UNSIGNED +) ENGINE=COLUMNSTORE; +INSERT INTO test_mult4 (indemnity_paid, n_clms) VALUES (-10, 1); +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult4; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "*" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult4; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "+" using value(s): -10.000000 1.000000 +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult4; +indemnity_paid n_clms (indemnity_paid + 9) + n_clms +-10 1 0 +SELECT indemnity_paid, n_clms, n_clms * indemnity_paid FROM test_mult4; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "*" using value(s): 1.000000 -10.000000 +SELECT indemnity_paid, n_clms, n_clms + indemnity_paid FROM test_mult4; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "+" using value(s): 1.000000 -10.000000 +SELECT indemnity_paid, n_clms, n_clms + (indemnity_paid + 9) FROM test_mult4; +indemnity_paid n_clms n_clms + (indemnity_paid + 9) +-10 1 0 +SELECT indemnity_paid, n_clms, n_clms - 2 FROM test_mult4; +ERROR HY000: Internal error: MCS-2053: The result is out of range for function "-" using value(s): 1.000000 2.000000 +DROP DATABASE MCOL5568; diff --git a/mysql-test/columnstore/basic/t/MCOL-5568-out-of-range.test b/mysql-test/columnstore/basic/t/MCOL-5568-out-of-range.test new file mode 100644 index 000000000..013fe3512 --- /dev/null +++ b/mysql-test/columnstore/basic/t/MCOL-5568-out-of-range.test @@ -0,0 +1,109 @@ +--disable_warnings +DROP DATABASE IF EXISTS MCOL5568; +--enable_warnings + +CREATE DATABASE MCOL5568; + +USE MCOL5568; + +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); + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult; + +# not an error. +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult; + +CREATE TABLE test_mult2 ( + +indemnity_paid TINYINT, + +n_clms TINYINT UNSIGNED + +) ENGINE=COLUMNSTORE; + +INSERT INTO test_mult2 (indemnity_paid, n_clms) VALUES (-10, 1); + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult2; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult2; + +# not an error. +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult2; + +CREATE TABLE test_mult3 ( + +indemnity_paid SMALLINT, + +n_clms TINYINT UNSIGNED + +) ENGINE=COLUMNSTORE; + +INSERT INTO test_mult3 (indemnity_paid, n_clms) VALUES (-10, 1); + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult3; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult3; + +# not an error. +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult3; + +CREATE TABLE test_mult4 ( + +indemnity_paid INTEGER, + +n_clms TINYINT UNSIGNED + +) ENGINE=COLUMNSTORE; + +INSERT INTO test_mult4 (indemnity_paid, n_clms) VALUES (-10, 1); + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid * n_clms FROM test_mult4; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, indemnity_paid + n_clms FROM test_mult4; + +# not an error. +SELECT indemnity_paid, n_clms, (indemnity_paid + 9) + n_clms FROM test_mult4; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, n_clms * indemnity_paid FROM test_mult4; + +# an error. +--error 1815 +SELECT indemnity_paid, n_clms, n_clms + indemnity_paid FROM test_mult4; + +# not an error. +SELECT indemnity_paid, n_clms, n_clms + (indemnity_paid + 9) FROM test_mult4; + +# an error again. +--error 1815 +SELECT indemnity_paid, n_clms, n_clms - 2 FROM test_mult4; + +DROP DATABASE MCOL5568; +