diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 2d6a4cb7de..9b3f5b9410 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -629,15 +629,17 @@ numeric_out_sci(Numeric num, int scale) /* * numeric_normalize() - * - * Output function for numeric data type without trailing zeroes. + * Output function for numeric data type, suppressing insignificant trailing + * zeroes and then any trailing decimal point. The intent of this is to + * produce strings that are equal if and only if the input numeric values + * compare equal. */ char * numeric_normalize(Numeric num) { NumericVar x; char *str; - int orig, - last; + int last; /* * Handle NaN @@ -649,19 +651,25 @@ numeric_normalize(Numeric num) str = get_str_from_var(&x); - orig = last = strlen(str) - 1; - - for (;;) + /* If there's no decimal point, there's certainly nothing to remove. */ + if (strchr(str, '.') != NULL) { - if (last == 0 || str[last] != '0') - break; + /* + * Back up over trailing fractional zeroes. Since there is a decimal + * point, this loop will terminate safely. + */ + last = strlen(str) - 1; + while (str[last] == '0') + last--; - last--; + /* We want to get rid of the decimal point too, if it's now last. */ + if (str[last] == '.') + last--; + + /* Delete whatever we backed up over. */ + str[last + 1] = '\0'; } - if (last > 0 && last != orig) - str[last] = '\0'; - return str; }