RFC: Locale support for Numeric datatype

Started by Giuseppe Tanzilli - CSFabout 24 years ago1 messages
#1Giuseppe Tanzilli - CSF
g.tanzilli@gruppocsf.com
1 attachment(s)

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

Attachments:

postgresql_numeric_locale_20011217text/plain; name=postgresql_numeric_locale_20011217Download
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)