From 6fd7916c56f4ee963023e3f8ee75686580ee8264 Mon Sep 17 00:00:00 2001 From: Gagan Goel Date: Thu, 5 Nov 2020 18:09:10 -0500 Subject: [PATCH] MCOL-4188 Fix regression in a union subquery involving a numeric field. Since we now perform type promotion to wide decimals for aggregations involving numeric fields, we need to check for wide decimal in in and out ROWs and call the appropriate setter and getter functions. --- dbcon/joblist/tupleunion.cpp | 72 +++++++++++++++++++++++++------ utils/dataconvert/dataconvert.cpp | 28 ++++++++++-- 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/dbcon/joblist/tupleunion.cpp b/dbcon/joblist/tupleunion.cpp index 914bd850d..4344109f1 100644 --- a/dbcon/joblist/tupleunion.cpp +++ b/dbcon/joblist/tupleunion.cpp @@ -534,7 +534,11 @@ dec1: else val *= (uint64_t) pow((double) 10, (double) diff); - out->setIntField(val, i); + if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + out->setInt128Field(val, i); + else + out->setIntField(val, i); + break; } @@ -661,7 +665,11 @@ dec2: else val *= (uint64_t) pow((double) 10, (double) diff); - out->setIntField(val, i); + if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + out->setInt128Field(val, i); + else + out->setIntField(val, i); + break; } @@ -979,7 +987,7 @@ dec2: case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { -dec3: /* have to pick a scale to use for the double. using 5... */ +dec3: /* have to pick a scale to use for the double. using 5... */ uint32_t scale = 5; uint64_t ival = (uint64_t) (double) (val * pow((double) 10, (double) scale)); int diff = out->getScale(i) - scale; @@ -989,7 +997,11 @@ dec3: /* have to pick a scale to use for the double. using 5... */ else ival *= (uint64_t) pow((double) 10, (double) diff); - out->setIntField((int64_t) val, i); + if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + out->setInt128Field(ival, i); + else + out->setIntField(ival, i); + break; } @@ -1066,7 +1078,11 @@ dec4: /* have to pick a scale to use for the double. using 5... */ else ival *= (uint64_t) pow((double) 10, (double) diff); - out->setIntField((int64_t) val, i); + if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + out->setInt128Field(ival, i); + else + out->setIntField(ival, i); + break; } @@ -1083,8 +1099,19 @@ dec4: /* have to pick a scale to use for the double. using 5... */ case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { - int64_t val = in.getIntField(i); - uint32_t scale = in.getScale(i); + int64_t val; + int128_t val128; + bool isInputWide = false; + + if (in.getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + { + in.getInt128Field(i, val128); + isInputWide = true; + } + else + val = in.getIntField(i); + + uint32_t scale = in.getScale(i); switch (out->getColTypes()[i]) { @@ -1101,12 +1128,31 @@ dec4: /* have to pick a scale to use for the double. using 5... */ case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { - if (out->getScale(i) == scale) - out->setIntField(val, i); - else if (out->getScale(i) > scale) - out->setIntField(IDB_pow[out->getScale(i) - scale]*val, i); - else // should not happen, the output's scale is the largest - throw logic_error("TupleUnion::normalize(): incorrect scale setting"); + if (out->getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) + { + if (out->getScale(i) == scale) + out->setInt128Field(isInputWide ? val128 : val, i); + else if (out->getScale(i) > scale) + { + int128_t divisor = 1; + datatypes::getScaleDivisor(divisor, out->getScale(i) - scale); + int128_t temp = isInputWide ? divisor*val128 : divisor*val; + out->setInt128Field(temp, i); + } + else // should not happen, the output's scale is the largest + throw logic_error("TupleUnion::normalize(): incorrect scale setting"); + } + // If output type is narrow decimal, input type + // has to be narrow decimal as well. + else + { + if (out->getScale(i) == scale) + out->setIntField(val, i); + else if (out->getScale(i) > scale) + out->setIntField(IDB_pow[out->getScale(i) - scale]*val, i); + else // should not happen, the output's scale is the largest + throw logic_error("TupleUnion::normalize(): incorrect scale setting"); + } break; } diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 7c416c141..12a766976 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -3160,6 +3160,9 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione unionedType.colDataType = datatypes::SystemCatalog::DECIMAL; } + if (type.precision > unionedType.precision) + unionedType.precision = type.precision; + unionedType.scale = (type.scale > unionedType.scale) ? type.scale : unionedType.scale; break; @@ -3390,7 +3393,6 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione case datatypes::SystemCatalog::MEDINT: case datatypes::SystemCatalog::INT: case datatypes::SystemCatalog::BIGINT: - case datatypes::SystemCatalog::DECIMAL: case datatypes::SystemCatalog::FLOAT: case datatypes::SystemCatalog::DOUBLE: case datatypes::SystemCatalog::UTINYINT: @@ -3398,7 +3400,6 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione case datatypes::SystemCatalog::UMEDINT: case datatypes::SystemCatalog::UINT: case datatypes::SystemCatalog::UBIGINT: - case datatypes::SystemCatalog::UDECIMAL: case datatypes::SystemCatalog::UFLOAT: case datatypes::SystemCatalog::UDOUBLE: unionedType.colDataType = datatypes::SystemCatalog::DOUBLE; @@ -3406,6 +3407,16 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione unionedType.colWidth = sizeof(double); break; + case datatypes::SystemCatalog::DECIMAL: + case datatypes::SystemCatalog::UDECIMAL: + if (unionedType.colWidth != datatypes::MAXDECIMALWIDTH) + { + unionedType.colDataType = datatypes::SystemCatalog::DOUBLE; + unionedType.scale = 0; + unionedType.colWidth = sizeof(double); + } + break; + default: break; } @@ -3446,7 +3457,6 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione case datatypes::SystemCatalog::MEDINT: case datatypes::SystemCatalog::INT: case datatypes::SystemCatalog::BIGINT: - case datatypes::SystemCatalog::DECIMAL: case datatypes::SystemCatalog::FLOAT: case datatypes::SystemCatalog::DOUBLE: case datatypes::SystemCatalog::UTINYINT: @@ -3454,7 +3464,6 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione case datatypes::SystemCatalog::UMEDINT: case datatypes::SystemCatalog::UINT: case datatypes::SystemCatalog::UBIGINT: - case datatypes::SystemCatalog::UDECIMAL: case datatypes::SystemCatalog::UFLOAT: case datatypes::SystemCatalog::UDOUBLE: case datatypes::SystemCatalog::LONGDOUBLE: @@ -3464,6 +3473,17 @@ DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd &unione unionedType.precision = -1; break; + case datatypes::SystemCatalog::DECIMAL: + case datatypes::SystemCatalog::UDECIMAL: + if (unionedType.colWidth != datatypes::MAXDECIMALWIDTH) + { + unionedType.colDataType = datatypes::SystemCatalog::LONGDOUBLE; + unionedType.scale = (type.scale > unionedType.scale) ? type.scale : unionedType.scale; + unionedType.colWidth = sizeof(long double); + unionedType.precision = -1; + } + break; + default: break; }