From 1d2a926d446742f5c2324a69022218dbea4fb699 Mon Sep 17 00:00:00 2001 From: Jack Del Vecchio Date: Thu, 19 Sep 2024 14:10:52 +0000 Subject: [PATCH] HPCC-32687 Output large Decimals correctly --- common/deftype/defvalue.cpp | 2 +- rtl/eclrtl/rtlformat.cpp | 12 ++++---- rtl/eclrtl/rtlxml.cpp | 8 +++--- system/include/platform.h | 1 + testing/regress/ecl/decimalOutput.ecl | 34 +++++++++++++++++++++++ testing/regress/ecl/key/decimalOutput.xml | 21 ++++++++++++++ 6 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 testing/regress/ecl/decimalOutput.ecl create mode 100644 testing/regress/ecl/key/decimalOutput.xml diff --git a/common/deftype/defvalue.cpp b/common/deftype/defvalue.cpp index 47fd7ccc71d..1cbbf170a1d 100644 --- a/common/deftype/defvalue.cpp +++ b/common/deftype/defvalue.cpp @@ -2235,7 +2235,7 @@ const char *DecimalValue::generateCPP(StringBuffer &s, CompilerType compiler) const char *DecimalValue::getStringValue(StringBuffer &s) { - char strval[64]; + char strval[MAX_DECIMAL_CHARS]; BcdCriticalBlock bcdBlock; pushDecimalValue(); DecPopCString(sizeof(strval), strval); diff --git a/rtl/eclrtl/rtlformat.cpp b/rtl/eclrtl/rtlformat.cpp index aaae29422ec..0c728c859b9 100644 --- a/rtl/eclrtl/rtlformat.cpp +++ b/rtl/eclrtl/rtlformat.cpp @@ -1048,7 +1048,7 @@ void CFormEncodedWriter::outputReal(double field, const char *fieldname) void CFormEncodedWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; updateCurrentScalarItemInfo(fieldname); appendFormUrlEncodedName(out, curIdx, curItemPath, fieldname, flags); @@ -1065,7 +1065,7 @@ void CFormEncodedWriter::outputDecimal(const void *field, unsigned size, unsigne void CFormEncodedWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; updateCurrentScalarItemInfo(fieldname); appendFormUrlEncodedName(out, curIdx, curItemPath, fieldname, flags); @@ -1446,7 +1446,7 @@ void CommonCSVWriter::outputDecimal(const void* field, unsigned size, unsigned p return; StringBuffer v; - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; BcdCriticalBlock bcdBlock; if (DecValid(true, size*2-1, field)) { @@ -1465,7 +1465,7 @@ void CommonCSVWriter::outputUDecimal(const void* field, unsigned size, unsigned return; StringBuffer v; - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; BcdCriticalBlock bcdBlock; if (DecValid(false, size*2, field)) { @@ -2117,7 +2117,7 @@ inline void outputEncodedXmlReal(double field, const char *fieldname, StringBuff inline void outputEncodedXmlDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; if (fieldname) out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">"); @@ -2139,7 +2139,7 @@ inline void outputEncodedXmlDecimal(const void *field, unsigned size, unsigned p inline void outputEncodedXmlUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; if (fieldname) out.append('<').append(fieldname).append(" xsi:type=\"xsd:decimal\">"); diff --git a/rtl/eclrtl/rtlxml.cpp b/rtl/eclrtl/rtlxml.cpp index 3467aa0224f..13d3bd1b5a5 100644 --- a/rtl/eclrtl/rtlxml.cpp +++ b/rtl/eclrtl/rtlxml.cpp @@ -95,7 +95,7 @@ void outputXmlDecimal(const void *field, unsigned size, unsigned precision, cons if (DecValid(true, size*2-1, field)) { Decimal temp; - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; temp.setDecimal(size, precision, field); temp.getCString(sizeof(dec), dec); @@ -118,7 +118,7 @@ void outputXmlUDecimal(const void *field, unsigned size, unsigned precision, con if (DecValid(false, size*2, field)) { Decimal temp; - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; temp.setUDecimal(size, precision, field); temp.getCString(sizeof(dec), dec); @@ -249,7 +249,7 @@ void outputJsonUnicode(unsigned len, const UChar *field, const char *fieldname, void outputJsonDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; appendJSONNameOrDelimit(out, fieldname); BcdCriticalBlock bcdBlock; @@ -265,7 +265,7 @@ void outputJsonDecimal(const void *field, unsigned size, unsigned precision, con void outputJsonUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname, StringBuffer &out) { - char dec[50]; + char dec[MAX_DECIMAL_CHARS]; appendJSONNameOrDelimit(out, fieldname); BcdCriticalBlock bcdBlock; diff --git a/system/include/platform.h b/system/include/platform.h index 2421016a4b1..e405ba7e622 100644 --- a/system/include/platform.h +++ b/system/include/platform.h @@ -485,6 +485,7 @@ inline bool DeleteFile(const char * name) { return unlink(name)==0; } #define MAX_DECIMAL_LEADING 32 // Maximum number of leading digits in a decimal field #define MAX_DECIMAL_PRECISION 32 // Maximum digits in a decimal field #define MAX_DECIMAL_DIGITS (MAX_DECIMAL_LEADING+MAX_DECIMAL_PRECISION) +#define MAX_DECIMAL_CHARS (MAX_DECIMAL_DIGITS+3) // Maximum digits with sign, decimal point, and null terminator #define strtok(a,b) j_strtok_deprecated(a,b) // will disappear at some point diff --git a/testing/regress/ecl/decimalOutput.ecl b/testing/regress/ecl/decimalOutput.ecl new file mode 100644 index 00000000000..fa19015ee6e --- /dev/null +++ b/testing/regress/ecl/decimalOutput.ecl @@ -0,0 +1,34 @@ +/*############################################################################## + + HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +############################################################################## */ + +// Decimals with less than 50 digits are output correctly +x := (DECIMAL48_32) '1234567890123456.12345678901234567890123456789012'; +y := (DECIMAL48_16) '12345678901234567890123456789012.1234567890123456'; +// For digits >= 50, the output was 50 '*' rather than the actual value +i := (DECIMAL49_32) '12345678901234567.12345678901234567890123456789012'; +j := (DECIMAL50_32) '123456789012345678.12345678901234567890123456789012'; +OUTPUT(x); +OUTPUT(y); +OUTPUT(i); +OUTPUT(j); + +a := (DECIMAL64_32) '12345678901234567890123456789012.12345678901234567890123456789012'; +// Max length Decimal with 64 digits and a negative sign +b := (DECIMAL64_32) '-12345678901234567890123456789011.12345678901234567890123456789012'; +OUTPUT(a); +OUTPUT(b); +OUTPUT(a + b); diff --git a/testing/regress/ecl/key/decimalOutput.xml b/testing/regress/ecl/key/decimalOutput.xml new file mode 100644 index 00000000000..aaceaa649b0 --- /dev/null +++ b/testing/regress/ecl/key/decimalOutput.xml @@ -0,0 +1,21 @@ + + 1234567890123456.12345678901234567890123456789012 + + + 12345678901234567890123456789012.1234567890123456 + + + 12345678901234567.12345678901234567890123456789012 + + + 123456789012345678.12345678901234567890123456789012 + + + 12345678901234567890123456789012.12345678901234567890123456789012 + + + -12345678901234567890123456789011.12345678901234567890123456789012 + + + 1 +