44 *
55 * Portions Copyright (c) 2002-2010, PostgreSQL Global Development Group
66 *
7- * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.53 2010/02/27 20:20:44 momjian Exp $
7+ * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.54 2010/04/22 01:55:52 itagaki Exp $
88 *
99 *-----------------------------------------------------------------------
1010 */
@@ -387,6 +387,28 @@ free_struct_lconv(struct lconv * s)
387387}
388388
389389
390+ /*
391+ * Return a strdup'ed string converted from the specified encoding to the
392+ * database encoding.
393+ */
394+ static char *
395+ db_encoding_strdup (int encoding ,const char * str )
396+ {
397+ char * pstr ;
398+ char * mstr ;
399+
400+ /* convert the string to the database encoding */
401+ pstr = (char * )pg_do_encoding_conversion (
402+ (unsignedchar * )str ,strlen (str ),
403+ encoding ,GetDatabaseEncoding ());
404+ mstr = strdup (pstr );
405+ if (pstr != str )
406+ pfree (pstr );
407+
408+ return mstr ;
409+ }
410+
411+
390412/*
391413 * Return the POSIX lconv struct (contains number/money formatting
392414 * information) with locale information for all categories.
@@ -398,6 +420,14 @@ PGLC_localeconv(void)
398420struct lconv * extlconv ;
399421char * save_lc_monetary ;
400422char * save_lc_numeric ;
423+ char * decimal_point ;
424+ char * grouping ;
425+ char * thousands_sep ;
426+ int encoding ;
427+
428+ #ifdef WIN32
429+ char * save_lc_ctype ;
430+ #endif
401431
402432/* Did we do it already? */
403433if (CurrentLocaleConvValid )
@@ -413,28 +443,48 @@ PGLC_localeconv(void)
413443if (save_lc_numeric )
414444save_lc_numeric = pstrdup (save_lc_numeric );
415445
416- setlocale (LC_MONETARY ,locale_monetary );
446+ #ifdef WIN32
447+ /* set user's value of ctype locale */
448+ save_lc_ctype = setlocale (LC_CTYPE ,NULL );
449+ if (save_lc_ctype )
450+ save_lc_ctype = pstrdup (save_lc_ctype );
451+ #endif
452+
453+ /* Get formatting information for numeric */
454+ #ifdef WIN32
455+ setlocale (LC_CTYPE ,locale_numeric );
456+ #endif
417457setlocale (LC_NUMERIC ,locale_numeric );
458+ extlconv = localeconv ();
459+ encoding = pg_get_encoding_from_locale (locale_numeric );
460+
461+ decimal_point = db_encoding_strdup (encoding ,extlconv -> decimal_point );
462+ thousands_sep = db_encoding_strdup (encoding ,extlconv -> thousands_sep );
463+ grouping = strdup (extlconv -> grouping );
418464
419- /* Get formatting information */
465+ /* Get formatting information for monetary */
466+ #ifdef WIN32
467+ setlocale (LC_CTYPE ,locale_monetary );
468+ #endif
469+ setlocale (LC_MONETARY ,locale_monetary );
420470extlconv = localeconv ();
471+ encoding = pg_get_encoding_from_locale (locale_monetary );
421472
422473/*
423474 * Must copy all values since restoring internal settings may overwrite
424475 * localeconv()'s results.
425476 */
426477CurrentLocaleConv = * extlconv ;
427- CurrentLocaleConv .currency_symbol = strdup ( extlconv -> currency_symbol ) ;
428- CurrentLocaleConv .decimal_point = strdup ( extlconv -> decimal_point ) ;
429- CurrentLocaleConv .grouping = strdup ( extlconv -> grouping ) ;
430- CurrentLocaleConv .thousands_sep = strdup ( extlconv -> thousands_sep );
431- CurrentLocaleConv .int_curr_symbol = strdup ( extlconv -> int_curr_symbol );
432- CurrentLocaleConv .mon_decimal_point = strdup ( extlconv -> mon_decimal_point );
478+ CurrentLocaleConv .decimal_point = decimal_point ;
479+ CurrentLocaleConv .grouping = grouping ;
480+ CurrentLocaleConv .thousands_sep = thousands_sep ;
481+ CurrentLocaleConv .int_curr_symbol = db_encoding_strdup ( encoding , extlconv -> int_curr_symbol );
482+ CurrentLocaleConv .currency_symbol = db_encoding_strdup ( encoding , extlconv -> currency_symbol );
483+ CurrentLocaleConv .mon_decimal_point = db_encoding_strdup ( encoding , extlconv -> mon_decimal_point );
433484CurrentLocaleConv .mon_grouping = strdup (extlconv -> mon_grouping );
434- CurrentLocaleConv .mon_thousands_sep = strdup (extlconv -> mon_thousands_sep );
435- CurrentLocaleConv .negative_sign = strdup (extlconv -> negative_sign );
436- CurrentLocaleConv .positive_sign = strdup (extlconv -> positive_sign );
437- CurrentLocaleConv .n_sign_posn = extlconv -> n_sign_posn ;
485+ CurrentLocaleConv .mon_thousands_sep = db_encoding_strdup (encoding ,extlconv -> mon_thousands_sep );
486+ CurrentLocaleConv .negative_sign = db_encoding_strdup (encoding ,extlconv -> negative_sign );
487+ CurrentLocaleConv .positive_sign = db_encoding_strdup (encoding ,extlconv -> positive_sign );
438488
439489/* Try to restore internal settings */
440490if (save_lc_monetary )
@@ -449,6 +499,15 @@ PGLC_localeconv(void)
449499pfree (save_lc_numeric );
450500}
451501
502+ #ifdef WIN32
503+ /* try to restore internal ctype settings */
504+ if (save_lc_ctype )
505+ {
506+ setlocale (LC_CTYPE ,save_lc_ctype );
507+ pfree (save_lc_ctype );
508+ }
509+ #endif
510+
452511CurrentLocaleConvValid = true;
453512return & CurrentLocaleConv ;
454513}