From 9f4231f87ff55acd4400cbf3f08183d332f9c4c8 Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Thu, 27 Jun 2024 23:31:03 +0300 Subject: [PATCH] MCOL-5708 Calculate precision and scale for constant decimal. (#3227) This patch calculates precision and scale for constant decimal value for SUM aggregation function. --- datatypes/mcs_datatype.cpp | 35 +++++++++++++++++++ datatypes/mcs_datatype.h | 2 ++ .../columnstore/bugfixes/mcol-5708.result | 17 +++++++++ .../columnstore/bugfixes/mcol-5708.test | 31 ++++++++++++++++ utils/rowgroup/rowaggregation.cpp | 7 ++-- 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 mysql-test/columnstore/bugfixes/mcol-5708.result create mode 100644 mysql-test/columnstore/bugfixes/mcol-5708.test diff --git a/datatypes/mcs_datatype.cpp b/datatypes/mcs_datatype.cpp index fbc6f5e23..f1a7414de 100644 --- a/datatypes/mcs_datatype.cpp +++ b/datatypes/mcs_datatype.cpp @@ -58,6 +58,41 @@ int128_t SystemCatalog::TypeAttributesStd::decimal128FromString(const std::strin return result; } +// 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; + } +} + int128_t SystemCatalog::TypeAttributesStd::decimal128FromString(const utils::NullString& value, bool* saturate) const { diff --git a/datatypes/mcs_datatype.h b/datatypes/mcs_datatype.h index 11ccaa1da..561f3fca4 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); + class SystemCatalog { public: 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 14712ff11..267f0c46e 100644 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -3702,10 +3702,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); execplan::CalpontSystemCatalog::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;