diff --git a/datatypes/mcs_datatype.cpp b/datatypes/mcs_datatype.cpp index fbeaa709d..f8243c542 100644 --- a/datatypes/mcs_datatype.cpp +++ b/datatypes/mcs_datatype.cpp @@ -66,6 +66,41 @@ int128_t TypeAttributesStd::decimal128FromString(const utils::NullString& value, return decimal128FromString(value.unsafeStringRef(), saturate); } +// SQL parser checks that given `value` is in a valid format. +// The first symbol can be `-`. The `value` can contain `.` symbol. +void decimalPrecisionAndScale(const utils::NullString& value, int& precision, int& scale) +{ + if (value.isNull()) + { + scale = 0; + precision = -1; + return; + } + + const auto strValue = value.unsafeStringRef(); + if (strValue.empty()) + { + scale = 0; + precision = -1; + return; + } + + const int len = strValue.size(); + const auto dotIndex = strValue.find('.'); + const int minExists = strValue.front() == '-' ? 1 : 0; + + if (dotIndex == std::string::npos) + { + scale = 0; + precision = len - minExists; + } + else + { + scale = len - dotIndex - 1; + precision = len - 1 - minExists; + } +} + const string& TypeHandlerSInt8::name() const { static const string xname = "TINYINT"; diff --git a/datatypes/mcs_datatype.h b/datatypes/mcs_datatype.h index 8db04d353..a7e869433 100644 --- a/datatypes/mcs_datatype.h +++ b/datatypes/mcs_datatype.h @@ -125,6 +125,8 @@ struct WidthToSIntegralType<16> : _WidthToSIntegralType<16, int128_t> { }; +void decimalPrecisionAndScale(const utils::NullString& value, int &precision, int &scale); + // XXX: It is assumed here that ALL TYPES have width, scale and precision. // XXX: And then some of them have the type tag itself. // XXX: But, all types have type tag, some need explicit width (decimals, for example) diff --git a/mysql-test/columnstore/bugfixes/mcol-5708.result b/mysql-test/columnstore/bugfixes/mcol-5708.result new file mode 100644 index 000000000..65b215812 --- /dev/null +++ b/mysql-test/columnstore/bugfixes/mcol-5708.result @@ -0,0 +1,17 @@ +DROP DATABASE IF EXISTS mcol_5708; +CREATE DATABASE mcol_5708; +USE mcol_5708; +CREATE TABLE test ( +`f_int` int(10) unsigned NOT NULL DEFAULT 0, +`f_dec14x2` decimal(14,2) NOT NULL DEFAULT 0.00, +`f_dec14x4` decimal(14,4) NOT NULL DEFAULT 0.0000 +) ENGINE=columnstore DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +insert into test (f_int,f_dec14x4, f_dec14x2) values (1, 0.1, 0.1); +select +f_int, sum(f_dec14x2), sum(f_dec14x4), +sum(-200.000001), sum(0), sum(0.0), sum(11.000011), sum(12e-4), sum(1e+4), +sum(-0.0), sum(-1 - 1.1), sum(--12), sum(+20), sum(13) +from test group by 1; +f_int sum(f_dec14x2) sum(f_dec14x4) sum(-200.000001) sum(0) sum(0.0) sum(11.000011) sum(12e-4) sum(1e+4) sum(-0.0) sum(-1 - 1.1) sum(--12) sum(+20) sum(13) +1 0.10 0.1000 -200.000001 0 0.0 11.000011 0.0012 10000 0.0 -2.1 12 20 13 +DROP DATABASE mcol_5708; diff --git a/mysql-test/columnstore/bugfixes/mcol-5708.test b/mysql-test/columnstore/bugfixes/mcol-5708.test new file mode 100644 index 000000000..7b04d8274 --- /dev/null +++ b/mysql-test/columnstore/bugfixes/mcol-5708.test @@ -0,0 +1,31 @@ +# +# MCOL-5708 +# + +--source ../include/have_columnstore.inc + +--disable_warnings +DROP DATABASE IF EXISTS mcol_5708; +--enable_warnings +CREATE DATABASE mcol_5708; +USE mcol_5708; + +CREATE TABLE test ( + `f_int` int(10) unsigned NOT NULL DEFAULT 0, + `f_dec14x2` decimal(14,2) NOT NULL DEFAULT 0.00, + `f_dec14x4` decimal(14,4) NOT NULL DEFAULT 0.0000 +) ENGINE=columnstore DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; + + +insert into test (f_int,f_dec14x4, f_dec14x2) values (1, 0.1, 0.1); + +select +f_int, sum(f_dec14x2), sum(f_dec14x4), +sum(-200.000001), sum(0), sum(0.0), sum(11.000011), sum(12e-4), sum(1e+4), +sum(-0.0), sum(-1 - 1.1), sum(--12), sum(+20), sum(13) +from test group by 1; + + +--disable_warnings +DROP DATABASE mcol_5708; +--enable_warnings diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index b341c40c4..f2d5ec2a8 100644 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -3821,10 +3821,13 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData auto width = fRow.getColumnWidth(colOut); if (width == datatypes::MAXDECIMALWIDTH) { + int precision, scale; + // MCOL-5708 Calculate precision and scale based on the given value. + datatypes::decimalPrecisionAndScale(aggData.fConstValue, precision, scale); datatypes::TypeHolderStd colType; colType.colWidth = width; - colType.precision = fRow.getPrecision(i); - colType.scale = fRow.getScale(i); + colType.precision = precision; + colType.scale = scale; colType.colDataType = colDataType; int128_t constValue = colType.decimal128FromString(aggData.fConstValue); int128_t sum;