diff --git a/src/common/backend/utils/adt/formatting.cpp b/src/common/backend/utils/adt/formatting.cpp index b8cad6dda1274837f8a5aab1076a3a13b671b9e6..394e45306149d7b9a5463f5ad29beb6e1123dffc 100644 --- a/src/common/backend/utils/adt/formatting.cpp +++ b/src/common/backend/utils/adt/formatting.cpp @@ -4636,6 +4636,12 @@ Datum blob_to_char_default(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } +Datum unknown_to_char2(PG_FUNCTION_ARGS) +{ + Datum result = DirectFunctionCall2(numeric_to_char, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)); + PG_RETURN_DATUM(result); +} + /* --------------------- * TO_TIMESTAMP() * @@ -7066,20 +7072,24 @@ Datum numeric_to_text_number(PG_FUNCTION_ARGS) // Number description: fmt NUMDesc numDesc; bool shouldFree = false; + fmt = PG_GETARG_TEXT_P(4); int len = VARSIZE(fmt) - VARHDRSZ; FormatNode* format = NUM_cache(len, &numDesc, fmt, &shouldFree); // Integer digits - unsigned int formatPrecision = Max(0, numDesc.pre); + unsigned int formatPrePrecision = Max(0, numDesc.pre); + // Decimal digits + unsigned int formatPostPrecision = Max(0, numDesc.post); if (shouldFree) pfree_ext(format); // Calculate the formatPrecision power of 10. - double powerOfMax = pow(10, formatPrecision); + double powerOfPreMax = pow(10, formatPrePrecision) - 1; + double powerOfPostMax = (pow(10, formatPostPrecision) - 1) / pow(10, formatPostPrecision); // into numeric_float8 func double defaultValue = (double)DatumGetFloat8(DirectFunctionCall1(numeric_float8, NumericGetDatum(defaultNumVal))); - if (defaultValue > (powerOfMax - 1)) { + if (defaultValue > (powerOfPreMax + powerOfPostMax)) { ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("Exceeding the maximum value required by fmt"))); } @@ -7148,6 +7158,7 @@ Datum numeric_to_default_without_defaultval(PG_FUNCTION_ARGS) result = to_numeric_number_internal_without_fmt(default_num_val, PG_GET_COLLATION(), &resultNull); } else { + fmt = PG_GETARG_TEXT_P(4); result = to_numeric_to_number_internal(default_num_val, fmt, PG_GET_COLLATION(), &resultNull); } diff --git a/src/test/regress/expected/to_number_default.out b/src/test/regress/expected/to_number_default.out index 0fc7b2da0826a422d3eda06b7e0e6c226805cdd6..43be63f8b054e181733d730e763b054928810cc8 100644 --- a/src/test/regress/expected/to_number_default.out +++ b/src/test/regress/expected/to_number_default.out @@ -280,6 +280,18 @@ SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; 3.14 (7 rows) +SELECT to_number('<1234>' DEFAULT 999 ON CONVERSION ERROR,'PR9999999'); +ERROR: "9" must be ahead of "PR" +CONTEXT: referenced column: to_number +SELECT TO_NUMBER('1234.56' default 999 on conversion error ,'99.99'); +ERROR: Exceeding the maximum value required by fmt +CONTEXT: referenced column: to_number +SELECT TO_NUMBER('1234.56' default 999.1 on conversion error ,'999.99'); + to_number +----------- + 999.1 +(1 row) + SELECT TO_NUMBER(c2 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1; to_number ----------------------------------------- diff --git a/src/test/regress/sql/to_number_default.sql b/src/test/regress/sql/to_number_default.sql index 15516dbf67d2dbfe50dca1cf33209e2ab72c182f..76df3a529e9c96567be5888a3be6d21b1f819a7c 100644 --- a/src/test/regress/sql/to_number_default.sql +++ b/src/test/regress/sql/to_number_default.sql @@ -60,6 +60,9 @@ SELECT TO_NUMBER(c1 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1; SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef +SELECT to_number('<1234>' DEFAULT 999 ON CONVERSION ERROR,'PR9999999'); +SELECT TO_NUMBER('1234.56' default 999 on conversion error ,'99.99'); +SELECT TO_NUMBER('1234.56' default 999.1 on conversion error ,'999.99'); SELECT TO_NUMBER(c2 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1; SELECT TO_NUMBER(c2 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1; @@ -283,4 +286,4 @@ SELECT * FROM tonumber_exec ORDER BY c1; DROP TABLE tonumber; DROP TABLE tonumber_exec; -drop schema if exists func_to_number cascade; \ No newline at end of file +drop schema if exists func_to_number cascade;