aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/numeric.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r--src/backend/utils/adt/numeric.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 2d6a4cb7de2..9b3f5b94107 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,18 +651,24 @@ 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--;
- if (last > 0 && last != orig)
- str[last] = '\0';
+ /* Delete whatever we backed up over. */
+ str[last + 1] = '\0';
+ }
return str;
}