diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index e14d7bcc13..d5ff246c7b 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -917,7 +917,7 @@ typedef struct NUMProc num_count, /* number of write digits */ num_in, /* is inside number */ num_curr, /* current position in number */ - num_pre, /* space before first number */ + out_pre_spaces, /* spaces before first digit */ read_dec, /* to_number - was read dec. point */ read_post, /* to_number - number of dec. digit */ @@ -975,10 +975,11 @@ static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *should static char *int_to_roman(int number); static void NUM_prepare_locale(NUMProc *Np); static char *get_last_relevant_decnum(char *num); -static void NUM_numpart_from_char(NUMProc *Np, int id, int plen); +static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len); static void NUM_numpart_to_char(NUMProc *Np, int id); -static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, - int plen, int sign, bool is_to_char, Oid collid); +static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, + char *number, int from_char_input_len, int to_char_out_pre_spaces, + int sign, bool is_to_char, Oid collid); static DCHCacheEntry *DCH_cache_search(char *str); static DCHCacheEntry *DCH_cache_getnew(char *str); @@ -4054,7 +4055,7 @@ get_last_relevant_decnum(char *num) * ---------- */ static void -NUM_numpart_from_char(NUMProc *Np, int id, int plen) +NUM_numpart_from_char(NUMProc *Np, int id, int input_len) { bool isread = FALSE; @@ -4066,8 +4067,8 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen) if (*Np->inout_p == ' ') Np->inout_p++; -#define OVERLOAD_TEST (Np->inout_p >= Np->inout + plen) -#define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s) +#define OVERLOAD_TEST (Np->inout_p >= Np->inout + input_len) +#define AMOUNT_TEST(_s) (input_len-(Np->inout_p-Np->inout) >= _s) if (*Np->inout_p == ' ') Np->inout_p++; @@ -4206,7 +4207,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen) * next char is not digit */ if (IS_LSIGN(Np->Num) && isread && - (Np->inout_p + 1) <= Np->inout + plen && + (Np->inout_p + 1) <= Np->inout + input_len && !isdigit((unsigned char) *(Np->inout_p + 1))) { int x; @@ -4301,7 +4302,7 @@ NUM_numpart_to_char(NUMProc *Np, int id) * handle "9.9" --> " .1" */ if (Np->sign_wrote == FALSE && - (Np->num_curr >= Np->num_pre || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) && + (Np->num_curr >= Np->out_pre_spaces || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) && (IS_PREDEC_SPACE(Np) == FALSE || (Np->last_relevant && *Np->last_relevant == '.'))) { if (IS_LSIGN(Np->Num)) @@ -4345,7 +4346,7 @@ NUM_numpart_to_char(NUMProc *Np, int id) */ if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC) { - if (Np->num_curr < Np->num_pre && + if (Np->num_curr < Np->out_pre_spaces && (Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num))) { /* @@ -4358,7 +4359,7 @@ NUM_numpart_to_char(NUMProc *Np, int id) } } else if (IS_ZERO(Np->Num) && - Np->num_curr < Np->num_pre && + Np->num_curr < Np->out_pre_spaces && Np->Num->zero_start <= Np->num_curr) { /* @@ -4430,7 +4431,7 @@ NUM_numpart_to_char(NUMProc *Np, int id) ++Np->number_p; } - end = Np->num_count + (Np->num_pre ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0); + end = Np->num_count + (Np->out_pre_spaces ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0); if (Np->last_relevant && Np->last_relevant == Np->number_p) end = Np->num_curr; @@ -4456,13 +4457,10 @@ NUM_numpart_to_char(NUMProc *Np, int id) ++Np->num_curr; } -/* - * Note: 'plen' is used in FROM_CHAR conversion and it's length of - * input (inout). In TO_CHAR conversion it's space before first number. - */ static char * -NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, - int plen, int sign, bool is_to_char, Oid collid) +NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, + char *number, int from_char_input_len, int to_char_out_pre_spaces, + int sign, bool is_to_char, Oid collid) { FormatNode *n; NUMProc _Np, @@ -4502,7 +4500,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, errmsg("\"RN\" not supported for input"))); Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post = - Np->Num->pre = Np->num_pre = Np->sign = 0; + Np->Num->pre = Np->out_pre_spaces = Np->sign = 0; if (IS_FILLMODE(Np->Num)) { @@ -4560,7 +4558,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, if (is_to_char) { - Np->num_pre = plen; + Np->out_pre_spaces = to_char_out_pre_spaces; if (IS_FILLMODE(Np->Num) && IS_DECIMAL(Np->Num)) { @@ -4570,22 +4568,22 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, * If any '0' specifiers are present, make sure we don't strip * those digits. */ - if (Np->last_relevant && Np->Num->zero_end > Np->num_pre) + if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces) { char *last_zero; - last_zero = Np->number + (Np->Num->zero_end - Np->num_pre); + last_zero = Np->number + (Np->Num->zero_end - Np->out_pre_spaces); if (Np->last_relevant < last_zero) Np->last_relevant = last_zero; } } - if (Np->sign_wrote == FALSE && Np->num_pre == 0) + if (Np->sign_wrote == FALSE && Np->out_pre_spaces == 0) ++Np->num_count; } else { - Np->num_pre = 0; + Np->out_pre_spaces = 0; *Np->number = ' '; /* sign space */ *(Np->number + 1) = '\0'; } @@ -4601,7 +4599,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, Np->Num->pre, Np->Num->post, Np->num_count, - Np->num_pre, + Np->out_pre_spaces, Np->sign_wrote ? "Yes" : "No", IS_ZERO(Np->Num) ? "Yes" : "No", Np->Num->zero_start, @@ -4636,7 +4634,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, /* * Check non-string inout end */ - if (Np->inout_p >= Np->inout + plen) + if (Np->inout_p >= Np->inout + from_char_input_len) break; } @@ -4666,7 +4664,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, } else { - NUM_numpart_from_char(Np, n->key->id, plen); + NUM_numpart_from_char(Np, n->key->id, from_char_input_len); break; /* switch() case: */ } @@ -4891,7 +4889,7 @@ do { \ do { \ int len; \ \ - NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true, PG_GET_COLLATION()); \ + NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \ \ if (shouldFree) \ pfree(format); \ @@ -4933,7 +4931,7 @@ numeric_to_number(PG_FUNCTION_ARGS) numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1); NUM_processor(format, &Num, VARDATA(value), numstr, - VARSIZE(value) - VARHDRSZ, 0, false, PG_GET_COLLATION()); + VARSIZE(value) - VARHDRSZ, 0, 0, false, PG_GET_COLLATION()); scale = Num.post; precision = Max(0, Num.pre) + scale; @@ -4962,7 +4960,7 @@ numeric_to_char(PG_FUNCTION_ARGS) FormatNode *format; text *result; bool shouldFree; - int plen = 0, + int out_pre_spaces = 0, sign = 0; char *numstr, *orgnum, @@ -5016,7 +5014,7 @@ numeric_to_char(PG_FUNCTION_ARGS) } else { - int len; + int numstr_pre_len; Numeric val = value; if (IS_MULTI(&Num)) @@ -5051,14 +5049,17 @@ numeric_to_char(PG_FUNCTION_ARGS) sign = '+'; numstr = orgnum; } - if ((p = strchr(numstr, '.'))) - len = p - numstr; - else - len = strlen(numstr); - if (Num.pre > len) - plen = Num.pre - len; - else if (len > Num.pre) + if ((p = strchr(numstr, '.'))) + numstr_pre_len = p - numstr; + else + numstr_pre_len = strlen(numstr); + + /* needs padding? */ + if (numstr_pre_len < Num.pre) + out_pre_spaces = Num.pre - numstr_pre_len; + /* overflowed prefix digit format? */ + else if (numstr_pre_len > Num.pre) { numstr = (char *) palloc(Num.pre + Num.post + 2); fill_str(numstr, '#', Num.pre + Num.post + 1); @@ -5083,7 +5084,7 @@ int4_to_char(PG_FUNCTION_ARGS) FormatNode *format; text *result; bool shouldFree; - int plen = 0, + int out_pre_spaces = 0, sign = 0; char *numstr, *orgnum; @@ -5113,7 +5114,7 @@ int4_to_char(PG_FUNCTION_ARGS) } else { - int len; + int numstr_pre_len; if (IS_MULTI(&Num)) { @@ -5134,22 +5135,26 @@ int4_to_char(PG_FUNCTION_ARGS) } else sign = '+'; - len = strlen(orgnum); + numstr_pre_len = strlen(orgnum); + + /* post-decimal digits? Pad out with zeros. */ if (Num.post) { - numstr = (char *) palloc(len + Num.post + 2); + numstr = (char *) palloc(numstr_pre_len + Num.post + 2); strcpy(numstr, orgnum); - *(numstr + len) = '.'; - memset(numstr + len + 1, '0', Num.post); - *(numstr + len + Num.post + 1) = '\0'; + *(numstr + numstr_pre_len) = '.'; + memset(numstr + numstr_pre_len + 1, '0', Num.post); + *(numstr + numstr_pre_len + Num.post + 1) = '\0'; } else numstr = orgnum; - if (Num.pre > len) - plen = Num.pre - len; - else if (len > Num.pre) + /* needs padding? */ + if (numstr_pre_len < Num.pre) + out_pre_spaces = Num.pre - numstr_pre_len; + /* overflowed prefix digit format? */ + else if (numstr_pre_len > Num.pre) { numstr = (char *) palloc(Num.pre + Num.post + 2); fill_str(numstr, '#', Num.pre + Num.post + 1); @@ -5174,7 +5179,7 @@ int8_to_char(PG_FUNCTION_ARGS) FormatNode *format; text *result; bool shouldFree; - int plen = 0, + int out_pre_spaces = 0, sign = 0; char *numstr, *orgnum; @@ -5217,7 +5222,7 @@ int8_to_char(PG_FUNCTION_ARGS) } else { - int len; + int numstr_pre_len; if (IS_MULTI(&Num)) { @@ -5240,22 +5245,26 @@ int8_to_char(PG_FUNCTION_ARGS) } else sign = '+'; - len = strlen(orgnum); + numstr_pre_len = strlen(orgnum); + + /* post-decimal digits? Pad out with zeros. */ if (Num.post) { - numstr = (char *) palloc(len + Num.post + 2); + numstr = (char *) palloc(numstr_pre_len + Num.post + 2); strcpy(numstr, orgnum); - *(numstr + len) = '.'; - memset(numstr + len + 1, '0', Num.post); - *(numstr + len + Num.post + 1) = '\0'; + *(numstr + numstr_pre_len) = '.'; + memset(numstr + numstr_pre_len + 1, '0', Num.post); + *(numstr + numstr_pre_len + Num.post + 1) = '\0'; } else numstr = orgnum; - if (Num.pre > len) - plen = Num.pre - len; - else if (len > Num.pre) + /* needs padding? */ + if (numstr_pre_len < Num.pre) + out_pre_spaces = Num.pre - numstr_pre_len; + /* overflowed prefix digit format? */ + else if (numstr_pre_len > Num.pre) { numstr = (char *) palloc(Num.pre + Num.post + 2); fill_str(numstr, '#', Num.pre + Num.post + 1); @@ -5280,7 +5289,7 @@ float4_to_char(PG_FUNCTION_ARGS) FormatNode *format; text *result; bool shouldFree; - int plen = 0, + int out_pre_spaces = 0, sign = 0; char *numstr, *orgnum, @@ -5320,7 +5329,7 @@ float4_to_char(PG_FUNCTION_ARGS) else { float4 val = value; - int len; + int numstr_pre_len; if (IS_MULTI(&Num)) { @@ -5332,13 +5341,13 @@ float4_to_char(PG_FUNCTION_ARGS) orgnum = (char *) palloc(MAXFLOATWIDTH + 1); snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val)); - len = strlen(orgnum); - if (Num.pre > len) - plen = Num.pre - len; - if (len >= FLT_DIG) + numstr_pre_len = strlen(orgnum); + + /* adjust post digits to fit max float digits */ + if (numstr_pre_len >= FLT_DIG) Num.post = 0; - else if (Num.post + len > FLT_DIG) - Num.post = FLT_DIG - len; + else if (numstr_pre_len + Num.post > FLT_DIG) + Num.post = FLT_DIG - numstr_pre_len; snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val); if (*orgnum == '-') @@ -5351,14 +5360,17 @@ float4_to_char(PG_FUNCTION_ARGS) sign = '+'; numstr = orgnum; } - if ((p = strchr(numstr, '.'))) - len = p - numstr; - else - len = strlen(numstr); - if (Num.pre > len) - plen = Num.pre - len; - else if (len > Num.pre) + if ((p = strchr(numstr, '.'))) + numstr_pre_len = p - numstr; + else + numstr_pre_len = strlen(numstr); + + /* needs padding? */ + if (numstr_pre_len < Num.pre) + out_pre_spaces = Num.pre - numstr_pre_len; + /* overflowed prefix digit format? */ + else if (numstr_pre_len > Num.pre) { numstr = (char *) palloc(Num.pre + Num.post + 2); fill_str(numstr, '#', Num.pre + Num.post + 1); @@ -5383,7 +5395,7 @@ float8_to_char(PG_FUNCTION_ARGS) FormatNode *format; text *result; bool shouldFree; - int plen = 0, + int out_pre_spaces = 0, sign = 0; char *numstr, *orgnum, @@ -5423,7 +5435,7 @@ float8_to_char(PG_FUNCTION_ARGS) else { float8 val = value; - int len; + int numstr_pre_len; if (IS_MULTI(&Num)) { @@ -5433,13 +5445,13 @@ float8_to_char(PG_FUNCTION_ARGS) Num.pre += Num.multi; } orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1); - len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val)); - if (Num.pre > len) - plen = Num.pre - len; - if (len >= DBL_DIG) + numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val)); + + /* adjust post digits to fit max double digits */ + if (numstr_pre_len >= DBL_DIG) Num.post = 0; - else if (Num.post + len > DBL_DIG) - Num.post = DBL_DIG - len; + else if (numstr_pre_len + Num.post > DBL_DIG) + Num.post = DBL_DIG - numstr_pre_len; snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val); if (*orgnum == '-') @@ -5452,14 +5464,17 @@ float8_to_char(PG_FUNCTION_ARGS) sign = '+'; numstr = orgnum; } - if ((p = strchr(numstr, '.'))) - len = p - numstr; - else - len = strlen(numstr); - if (Num.pre > len) - plen = Num.pre - len; - else if (len > Num.pre) + if ((p = strchr(numstr, '.'))) + numstr_pre_len = p - numstr; + else + numstr_pre_len = strlen(numstr); + + /* needs padding? */ + if (numstr_pre_len < Num.pre) + out_pre_spaces = Num.pre - numstr_pre_len; + /* overflowed prefix digit format? */ + else if (numstr_pre_len > Num.pre) { numstr = (char *) palloc(Num.pre + Num.post + 2); fill_str(numstr, '#', Num.pre + Num.post + 1);