RFC: Locale support for Numeric datatype - Mailing list pgsql-hackers

From Giuseppe Tanzilli - CSF
Subject RFC: Locale support for Numeric datatype
Date
Msg-id 3C2054FC.4050906@gruppocsf.com
Whole thread Raw
List pgsql-hackers
Hi,
I got this patch working on 7.2b4,  uses locale setting for input/output
numeric datatype.
It do not modify the regression tests.

Any suggestion on How is implemented ?
How to change the regression test, to make it work on all the locale
settings ?

thanks
Giuseppe


--
-------------------------------------------------------
Giuseppe Tanzilli        g.tanzilli@gruppocsf.com
CSF Sistemi srl            phone ++39 0775 7771
Via del Ciavattino
Anagni FR
Italy


diff -u src/backend/utils/adt.orig/numeric.c src/backend/utils/adt/numeric.c
--- src/backend/utils/adt.orig/numeric.c    Mon Dec 17 18:35:15 2001
+++ src/backend/utils/adt/numeric.c    Mon Dec 17 18:27:59 2001
@@ -17,11 +17,15 @@
 #include <math.h>
 #include <errno.h>
 #include <sys/types.h>
+#ifdef USE_LOCALE
+#include <locale.h>
+#endif

 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/int8.h"
 #include "utils/numeric.h"
+#include "utils/pg_locale.h"

 /* ----------
  * Uncomment the following to enable compilation of dump_numeric()
@@ -2335,7 +2339,28 @@
     char       *cp = str;
     bool        have_dp = FALSE;
     int            i = 0;
+    char        dsymbol,
+                ssymbol,
+                psymbol,
+               *nsymbol;
+
+#ifdef USE_LOCALE
+    struct lconv *lconvert = PGLC_localeconv();
+
+    dsymbol = ((*lconvert->decimal_point != '\0') ? *lconvert->decimal_point : '.');
+    ssymbol = ((*lconvert->thousands_sep != '\0') ? *lconvert->thousands_sep : ',');
+    psymbol = ((*lconvert->positive_sign != '\0') ? *lconvert->positive_sign : '+');
+    nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
+#else
+    dsymbol = '.';
+    ssymbol = ',';
+    psymbol = '+';
+    nsymbol = "-";
+#endif

+
+
+
     while (*cp)
     {
         if (!isspace((unsigned char) *cp))
@@ -2348,26 +2373,23 @@
     dest->dscale = 0;
     dest->sign = NUMERIC_POS;

-    switch (*cp)
+    if(*cp == psymbol)
     {
-        case '+':
             dest->sign = NUMERIC_POS;
             cp++;
-            break;
-
-        case '-':
+    }
+    else if (*cp == nsymbol[0]) {
             dest->sign = NUMERIC_NEG;
             cp++;
-            break;
     }

-    if (*cp == '.')
+    if (*cp == (unsigned char) dsymbol)
     {
         have_dp = TRUE;
         cp++;
     }

-    if (!isdigit((unsigned char) *cp))
+    if (!isdigit((unsigned char) *cp) && *cp != dsymbol && *cp != ssymbol && *cp != nsymbol[0])
         elog(ERROR, "Bad numeric input format '%s'", str);

     while (*cp)
@@ -2380,7 +2402,7 @@
             else
                 dest->dscale++;
         }
-        else if (*cp == '.')
+        else if (*cp == dsymbol)
         {
             if (have_dp)
                 elog(ERROR, "Bad numeric input format '%s'", str);
@@ -2508,6 +2530,26 @@
     char       *cp;
     int            i;
     int            d;
+    char        dsymbol,
+                ssymbol,
+                psymbol,
+               *nsymbol;
+
+#ifdef USE_LOCALE
+    struct lconv *lconvert = PGLC_localeconv();
+
+    dsymbol = ((*lconvert->decimal_point != '\0') ? *lconvert->decimal_point : '.');
+    ssymbol = ((*lconvert->thousands_sep != '\0') ? *lconvert->thousands_sep : ',');
+    psymbol = ((*lconvert->positive_sign != '\0') ? *lconvert->positive_sign : '+');
+    nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-");
+#else
+    dsymbol = '.';
+    ssymbol = ',';
+    psymbol = '+';
+    nsymbol = "-";
+#endif
+
+

     /*
      * Check if we must round up before printing the value and do so.
@@ -2548,7 +2590,7 @@
      * Output a dash for negative values
      */
     if (var->sign == NUMERIC_NEG)
-        *cp++ = '-';
+        *cp++ = nsymbol[0];

     /*
      * Output all digits before the decimal point
@@ -2571,7 +2613,7 @@
      */
     if (dscale > 0)
     {
-        *cp++ = '.';
+        *cp++ = dsymbol;
         while (i >= -dscale)
         {
             if (i <= var->weight && d < var->ndigits)

pgsql-hackers by date:

Previous
From: Daniel Kalchev
Date:
Subject: Re: Thoughts on the location of configuration files
Next
From: Dave Page
Date:
Subject: Re: Thoughts on the location of configuration files