diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 46f45f6654..6ae02056d7 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -4655,6 +4655,8 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, FormatNode *n; NUMProc _Np, *Np = &_Np; + int separator_len; + bool noadd; MemSet(Np, 0, sizeof(NUMProc)); @@ -4808,6 +4810,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, * Locale */ NUM_prepare_locale(Np); + separator_len = strlen(Np->L_thousands_sep); /* * Processor direct cycle @@ -4819,6 +4822,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++) { + noadd = false; if (!Np->is_to_char) { /* @@ -4879,6 +4883,10 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, continue; } } + if (strncmp(Np->inout_p, Np->L_thousands_sep, separator_len) == 0) + Np->inout_p += separator_len - 1; + else + noadd = true; break; case NUM_G: @@ -4890,10 +4898,8 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, continue; else { - int x = strlen(Np->L_thousands_sep); - - memset(Np->inout_p, ' ', x); - Np->inout_p += x - 1; + memset(Np->inout_p, ' ', separator_len); + Np->inout_p += separator_len - 1; } } else @@ -4909,7 +4915,10 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, if (IS_FILLMODE(Np->Num)) continue; } - Np->inout_p += strlen(Np->L_thousands_sep) - 1; + if (strncmp(Np->inout_p, Np->L_thousands_sep, separator_len) == 0) + Np->inout_p += separator_len - 1; + else + noadd = true; } break; @@ -5030,7 +5039,8 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, if (Np->is_to_char) *Np->inout_p = n->character; } - Np->inout_p++; + if (!noadd) + Np->inout_p++; } if (Np->is_to_char) diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index ae0beb9b68..41b582de09 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -1925,3 +1925,36 @@ SELECT SUM((-9999)::numeric) FROM generate_series(1, 100000); -999900000 (1 row) +-- +-- Tests to regression test TODO item 'Fix to_number() handling for values not matching the format string' +-- +select to_number('34,50','999,99'); + to_number +----------- + 3450 +(1 row) + +select to_number('34,50','999G99'); + to_number +----------- + 3450 +(1 row) + +select to_number('12,34','999G99'); + to_number +----------- + 1234 +(1 row) + +select to_number('123,000','999G'); + to_number +----------- + 123 +(1 row) + +select to_number('123456','999G999'); + to_number +----------- + 123456 +(1 row) + diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql index b51225c47f..e1dd3a405c 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -1005,3 +1005,13 @@ select scale(-13.000000000000000); -- cases that need carry propagation SELECT SUM(9999::numeric) FROM generate_series(1, 100000); SELECT SUM((-9999)::numeric) FROM generate_series(1, 100000); + +-- +-- Tests to regression test TODO item 'Fix to_number() handling for values not matching the format string' +-- + +select to_number('34,50','999,99'); +select to_number('34,50','999G99'); +select to_number('12,34','999G99'); +select to_number('123,000','999G'); +select to_number('123456','999G999');