From 57589b382ed7f9a413213dd53595d1041fc4bfc7 Mon Sep 17 00:00:00 2001 From: JulianZhang Date: Thu, 7 Nov 2024 16:08:03 +0800 Subject: [PATCH] to_char(numeric) overflow return ######## --- src/common/backend/utils/adt/formatting.cpp | 51 +++-- src/test/regress/expected/to_char.out | 217 ++++++++++++++++++++ src/test/regress/parallel_schedule0B | 2 +- src/test/regress/sql/to_char.sql | 41 ++++ 4 files changed, 297 insertions(+), 14 deletions(-) create mode 100644 src/test/regress/expected/to_char.out create mode 100644 src/test/regress/sql/to_char.sql diff --git a/src/common/backend/utils/adt/formatting.cpp b/src/common/backend/utils/adt/formatting.cpp index 74c11d644..4f217e011 100644 --- a/src/common/backend/utils/adt/formatting.cpp +++ b/src/common/backend/utils/adt/formatting.cpp @@ -6566,6 +6566,10 @@ static char* NUM_processor(FormatNode* node, NUMDesc* Num, char* inout, char* nu */ \ len = strlen(VARDATA(result)); \ SET_VARSIZE(result, len + VARHDRSZ); \ + /* In A compatibility, all we need for overflow num is a pure "###" style str */ \ + if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && overflow) { \ + fill_str(VARDATA(result), '#', len); \ + } \ } while (0) @@ -6890,6 +6894,7 @@ Datum numeric_to_char(PG_FUNCTION_ARGS) FormatNode* format = NULL; text* result = NULL; bool shouldFree = false; + bool overflow = false; int len = 0, plen = 0, sign = 0; char *numstr = NULL, *orgnum = NULL, *p = NULL; Numeric x; @@ -6975,9 +6980,13 @@ Datum numeric_to_char(PG_FUNCTION_ARGS) if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - numstr = (char*)palloc(Num.pre + Num.post + 2); - fill_str(numstr, '#', Num.pre + Num.post + 1); - *(numstr + Num.pre) = '.'; + overflow = true; + // if overflow when A_FORMAT, do fill_str later. + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + numstr = (char*)palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); + *(numstr + Num.pre) = '.'; + } } } @@ -7004,6 +7013,7 @@ Datum int4_to_char(PG_FUNCTION_ARGS) FormatNode* format = NULL; text* result = NULL; bool shouldFree = false; + bool overflow = false; int len = 0, plen = 0, sign = 0; char *numstr = NULL, *orgnum = NULL; errno_t ret = EOK; @@ -7073,9 +7083,12 @@ Datum int4_to_char(PG_FUNCTION_ARGS) if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - numstr = (char*)palloc(Num.pre + Num.post + 2); - fill_str(numstr, '#', Num.pre + Num.post + 1); - *(numstr + Num.pre) = '.'; + overflow = true; + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + numstr = (char*)palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); + *(numstr + Num.pre) = '.'; + } } } @@ -7095,6 +7108,7 @@ Datum int8_to_char(PG_FUNCTION_ARGS) FormatNode* format = NULL; text* result = NULL; bool shouldFree = false; + bool overflow = false; int len = 0, plen = 0, sign = 0; char *numstr = NULL, *orgnum = NULL; errno_t ret = EOK; @@ -7174,8 +7188,11 @@ Datum int8_to_char(PG_FUNCTION_ARGS) if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - numstr = (char*)palloc(Num.pre + Num.post + 2); - fill_str(numstr, '#', Num.pre + Num.post + 1); + overflow = true; + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + numstr = (char*)palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); + } } } @@ -7195,6 +7212,7 @@ Datum float4_to_char(PG_FUNCTION_ARGS) FormatNode* format = NULL; text* result = NULL; bool shouldFree = false; + bool overflow = false; int len = 0, plen = 0, sign = 0; char *numstr = NULL, *orgnum = NULL, *p = NULL; errno_t ret = EOK; @@ -7282,8 +7300,11 @@ Datum float4_to_char(PG_FUNCTION_ARGS) if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - numstr = (char*)palloc(Num.pre + Num.post + 2); - fill_str(numstr, '#', Num.pre + Num.post + 1); + overflow = true; + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + numstr = (char*)palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); + } } } @@ -7303,6 +7324,7 @@ Datum float8_to_char(PG_FUNCTION_ARGS) FormatNode* format = NULL; text* result = NULL; bool shouldFree = false; + bool overflow = false; int len = 0, plen = 0, sign = 0; char *numstr = NULL, *orgnum = NULL, *p = NULL; errno_t ret = EOK; @@ -7390,9 +7412,12 @@ Datum float8_to_char(PG_FUNCTION_ARGS) if (Num.pre > len) plen = Num.pre - len; else if (len > Num.pre) { - numstr = (char*)palloc(Num.pre + Num.post + 2); - fill_str(numstr, '#', Num.pre + Num.post + 1); - *(numstr + Num.pre) = '.'; + overflow = true; + if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) { + numstr = (char*)palloc(Num.pre + Num.post + 2); + fill_str(numstr, '#', Num.pre + Num.post + 1); + *(numstr + Num.pre) = '.'; + } } } diff --git a/src/test/regress/expected/to_char.out b/src/test/regress/expected/to_char.out new file mode 100644 index 000000000..96e4e4116 --- /dev/null +++ b/src/test/regress/expected/to_char.out @@ -0,0 +1,217 @@ +-- to_char overflow case test +select to_char( 127::int4, '999'); + to_char +--------- + 127 +(1 row) + +select to_char( 126::int8, '999'); + to_char +--------- + 126 +(1 row) + +select to_char( 125.7::float4, '999D9'); + to_char +--------- + 125.7 +(1 row) + +select to_char( 125.9::float8, '999D9'); + to_char +--------- + 125.9 +(1 row) + +select to_char( 125.9::numeric, '999D9'); + to_char +--------- + 125.9 +(1 row) + +select to_char( 8e2, '999D9'); + to_char +--------- + 800.0 +(1 row) + +select to_char( 125.9::float8, '999.999'); + to_char +---------- + 125.900 +(1 row) + +select to_char( 125.9::numeric, '999.999'); + to_char +---------- + 125.900 +(1 row) + +select to_char( 8e2, '999.999'); + to_char +---------- + 800.000 +(1 row) + +select to_char( -127::int4, '999'); + to_char +--------- + -127 +(1 row) + +select to_char( -126::int8, '999'); + to_char +--------- + -126 +(1 row) + +select to_char( -125.7::float4, '999D9'); + to_char +--------- + -125.7 +(1 row) + +select to_char( -125.9::float8, '999D9'); + to_char +--------- + -125.9 +(1 row) + +select to_char( -125.9::numeric, '999D9'); + to_char +--------- + -125.9 +(1 row) + +select to_char( -8e2, '999D9'); + to_char +--------- + -800.0 +(1 row) + +select to_char( -125.9::float8, '999.999'); + to_char +---------- + -125.900 +(1 row) + +select to_char( -125.9::numeric, '999.999'); + to_char +---------- + -125.900 +(1 row) + +select to_char( -8e2, '999.999'); + to_char +---------- + -800.000 +(1 row) + +select to_char( 1287::int4, '999'); + to_char +--------- + #### +(1 row) + +select to_char( 1286::int8, '999'); + to_char +--------- + #### +(1 row) + +select to_char( 1285.7888::float4, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( 1285.9888::float8, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( 1285.8889::numeric, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( 8e99, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( 1285.9888::float8, '999.999'); + to_char +---------- + ######## +(1 row) + +select to_char( 1285.8889::numeric, '999.999'); + to_char +---------- + ######## +(1 row) + +select to_char( 8e99, '999.999'); + to_char +---------- + ######## +(1 row) + +select to_char( -1287::int4, '999'); + to_char +--------- + #### +(1 row) + +select to_char( -1286::int8, '999'); + to_char +--------- + #### +(1 row) + +select to_char( -1285.7888::float4, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( -1285.9888::float8, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( -1285.8889::numeric, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( -8e99, '999D9'); + to_char +--------- + ###### +(1 row) + +select to_char( -1285.9888::float8, '999.999'); + to_char +---------- + ######## +(1 row) + +select to_char( -1285.8889::numeric, '999.999'); + to_char +---------- + ######## +(1 row) + +select to_char( -8e99, '999.999'); + to_char +---------- + ######## +(1 row) + diff --git a/src/test/regress/parallel_schedule0B b/src/test/regress/parallel_schedule0B index 3957ed56b..29a7158fe 100644 --- a/src/test/regress/parallel_schedule0B +++ b/src/test/regress/parallel_schedule0B @@ -167,7 +167,7 @@ test: vec_mergejoin_aggregation llvm_vecagg llvm_vecagg2 llvm_vecagg3 llvm_vecha # ----------$ # The first group of parallel tests$ # ----------$ -test: boolean name oid bit txid uuid numeric_hide_tailing_zero rawlike +test: boolean name oid bit txid uuid numeric_hide_tailing_zero rawlike to_char #test: float8 numeric char varchar text int2 int4 float4 numeric_2 money # Depends on things setup during char, varchar and text diff --git a/src/test/regress/sql/to_char.sql b/src/test/regress/sql/to_char.sql new file mode 100644 index 000000000..11f6c5341 --- /dev/null +++ b/src/test/regress/sql/to_char.sql @@ -0,0 +1,41 @@ +-- to_char overflow case test +select to_char( 127::int4, '999'); +select to_char( 126::int8, '999'); +select to_char( 125.7::float4, '999D9'); +select to_char( 125.9::float8, '999D9'); +select to_char( 125.9::numeric, '999D9'); +select to_char( 8e2, '999D9'); +select to_char( 125.9::float8, '999.999'); +select to_char( 125.9::numeric, '999.999'); +select to_char( 8e2, '999.999'); + +select to_char( -127::int4, '999'); +select to_char( -126::int8, '999'); +select to_char( -125.7::float4, '999D9'); +select to_char( -125.9::float8, '999D9'); +select to_char( -125.9::numeric, '999D9'); +select to_char( -8e2, '999D9'); +select to_char( -125.9::float8, '999.999'); +select to_char( -125.9::numeric, '999.999'); +select to_char( -8e2, '999.999'); + +select to_char( 1287::int4, '999'); +select to_char( 1286::int8, '999'); +select to_char( 1285.7888::float4, '999D9'); +select to_char( 1285.9888::float8, '999D9'); +select to_char( 1285.8889::numeric, '999D9'); +select to_char( 8e99, '999D9'); +select to_char( 1285.9888::float8, '999.999'); +select to_char( 1285.8889::numeric, '999.999'); +select to_char( 8e99, '999.999'); + + +select to_char( -1287::int4, '999'); +select to_char( -1286::int8, '999'); +select to_char( -1285.7888::float4, '999D9'); +select to_char( -1285.9888::float8, '999D9'); +select to_char( -1285.8889::numeric, '999D9'); +select to_char( -8e99, '999D9'); +select to_char( -1285.9888::float8, '999.999'); +select to_char( -1285.8889::numeric, '999.999'); +select to_char( -8e99, '999.999');