2000-02-08 16:57:01 +01:00
|
|
|
/* -----------------------------------------------------------------------
|
2000-01-07 18:22:47 +01:00
|
|
|
* pg_locale.c
|
|
|
|
*
|
2000-11-25 23:43:08 +01:00
|
|
|
* The PostgreSQL locale utils.
|
2000-01-07 18:22:47 +01:00
|
|
|
*
|
|
|
|
*
|
2002-03-06 07:10:59 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.15 2002/03/06 06:10:14 momjian Exp $
|
2000-02-08 16:57:01 +01:00
|
|
|
*
|
2001-01-24 20:43:33 +01:00
|
|
|
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
|
2000-02-08 16:57:01 +01:00
|
|
|
*
|
2001-09-29 23:16:30 +02:00
|
|
|
* Karel Zak
|
2000-02-08 16:57:01 +01:00
|
|
|
*
|
|
|
|
* -----------------------------------------------------------------------
|
2000-01-07 18:22:47 +01:00
|
|
|
*/
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-01-07 18:22:47 +01:00
|
|
|
#include "postgres.h"
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-01-07 18:22:47 +01:00
|
|
|
#ifdef USE_LOCALE
|
|
|
|
|
|
|
|
#include <locale.h>
|
2001-09-29 23:16:30 +02:00
|
|
|
|
2000-01-07 18:22:47 +01:00
|
|
|
#include "utils/pg_locale.h"
|
|
|
|
|
|
|
|
/* #define DEBUG_LOCALE_UTILS */
|
|
|
|
|
|
|
|
|
2001-09-29 23:16:30 +02:00
|
|
|
static bool CurrentLocaleConvValid = false;
|
|
|
|
static struct lconv CurrentLocaleConv;
|
|
|
|
|
2000-08-29 06:41:48 +02:00
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
static void PGLC_setlocale(PG_LocaleCategories *lc);
|
2000-11-25 23:43:08 +01:00
|
|
|
|
2000-01-07 18:22:47 +01:00
|
|
|
/*------
|
2001-10-25 07:50:21 +02:00
|
|
|
* Frees memory used in PG_LocaleCategories -- this memory is
|
2001-09-29 23:16:30 +02:00
|
|
|
* allocated in PGLC_current().
|
|
|
|
*------
|
|
|
|
*/
|
|
|
|
void
|
2001-10-25 07:50:21 +02:00
|
|
|
PGLC_free_categories(PG_LocaleCategories *lc)
|
2001-09-29 23:16:30 +02:00
|
|
|
{
|
|
|
|
if (lc->lc_ctype)
|
|
|
|
pfree(lc->lc_ctype);
|
|
|
|
if (lc->lc_numeric)
|
|
|
|
pfree(lc->lc_numeric);
|
|
|
|
if (lc->lc_time)
|
|
|
|
pfree(lc->lc_time);
|
|
|
|
if (lc->lc_collate)
|
|
|
|
pfree(lc->lc_collate);
|
|
|
|
if (lc->lc_monetary);
|
2001-10-25 07:50:21 +02:00
|
|
|
pfree(lc->lc_monetary);
|
2001-09-29 23:16:30 +02:00
|
|
|
#ifdef LC_MESSAGES
|
|
|
|
if (lc->lc_messages)
|
|
|
|
pfree(lc->lc_messages);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------
|
|
|
|
* Return in PG_LocaleCategories the current locale settings.
|
|
|
|
*
|
|
|
|
* NB: strings are allocated in the current memory context!
|
2000-01-07 18:22:47 +01:00
|
|
|
*------
|
2000-04-12 19:17:23 +02:00
|
|
|
*/
|
2000-11-25 23:43:08 +01:00
|
|
|
void
|
2001-10-25 07:50:21 +02:00
|
|
|
PGLC_current(PG_LocaleCategories *lc)
|
2000-01-07 18:22:47 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
lc->lang = getenv("LANG");
|
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
lc->lc_ctype = pstrdup(setlocale(LC_CTYPE, NULL));
|
|
|
|
lc->lc_numeric = pstrdup(setlocale(LC_NUMERIC, NULL));
|
|
|
|
lc->lc_time = pstrdup(setlocale(LC_TIME, NULL));
|
|
|
|
lc->lc_collate = pstrdup(setlocale(LC_COLLATE, NULL));
|
|
|
|
lc->lc_monetary = pstrdup(setlocale(LC_MONETARY, NULL));
|
2000-06-29 03:19:36 +02:00
|
|
|
#ifdef LC_MESSAGES
|
2001-10-25 07:50:21 +02:00
|
|
|
lc->lc_messages = pstrdup(setlocale(LC_MESSAGES, NULL));
|
2000-06-29 03:19:36 +02:00
|
|
|
#endif
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
2000-01-07 18:22:47 +01:00
|
|
|
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
#ifdef DEBUG_LOCALE_UTILS
|
2000-01-07 18:22:47 +01:00
|
|
|
|
|
|
|
/*------
|
|
|
|
* Print a PG_LocaleCategories struct as DEBUG
|
|
|
|
*------
|
|
|
|
*/
|
2000-11-25 23:43:08 +01:00
|
|
|
static void
|
2001-10-25 07:50:21 +02:00
|
|
|
PGLC_debug_lc(PG_LocaleCategories *lc)
|
2000-01-07 18:22:47 +01:00
|
|
|
{
|
2000-06-29 03:19:36 +02:00
|
|
|
#ifdef LC_MESSAGES
|
Commit to match discussed elog() changes. Only update is that LOG is
now just below FATAL in server_min_messages. Added more text to
highlight ordering difference between it and client_min_messages.
---------------------------------------------------------------------------
REALLYFATAL => PANIC
STOP => PANIC
New INFO level the prints to client by default
New LOG level the prints to server log by default
Cause VACUUM information to print only to the client
NOTICE => INFO where purely information messages are sent
DEBUG => LOG for purely server status messages
DEBUG removed, kept as backward compatible
DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1 added
DebugLvl removed in favor of new DEBUG[1-5] symbols
New server_min_messages GUC parameter with values:
DEBUG[5-1], INFO, NOTICE, ERROR, LOG, FATAL, PANIC
New client_min_messages GUC parameter with values:
DEBUG[5-1], LOG, INFO, NOTICE, ERROR, FATAL, PANIC
Server startup now logged with LOG instead of DEBUG
Remove debug_level GUC parameter
elog() numbers now start at 10
Add test to print error message if older elog() values are passed to elog()
Bootstrap mode now has a -d that requires an argument, like postmaster
2002-03-02 22:39:36 +01:00
|
|
|
elog(LOG, "CURRENT LOCALE ENVIRONMENT:\n\nLANG: \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\nLC_MESSAGES:\t%s\n",
|
2001-09-29 23:16:30 +02:00
|
|
|
lc->lang,
|
|
|
|
lc->lc_ctype,
|
|
|
|
lc->lc_numeric,
|
|
|
|
lc->lc_time,
|
|
|
|
lc->lc_collate,
|
|
|
|
lc->lc_monetary,
|
|
|
|
lc->lc_messages);
|
2000-06-29 03:19:36 +02:00
|
|
|
#else
|
Commit to match discussed elog() changes. Only update is that LOG is
now just below FATAL in server_min_messages. Added more text to
highlight ordering difference between it and client_min_messages.
---------------------------------------------------------------------------
REALLYFATAL => PANIC
STOP => PANIC
New INFO level the prints to client by default
New LOG level the prints to server log by default
Cause VACUUM information to print only to the client
NOTICE => INFO where purely information messages are sent
DEBUG => LOG for purely server status messages
DEBUG removed, kept as backward compatible
DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1 added
DebugLvl removed in favor of new DEBUG[1-5] symbols
New server_min_messages GUC parameter with values:
DEBUG[5-1], INFO, NOTICE, ERROR, LOG, FATAL, PANIC
New client_min_messages GUC parameter with values:
DEBUG[5-1], LOG, INFO, NOTICE, ERROR, FATAL, PANIC
Server startup now logged with LOG instead of DEBUG
Remove debug_level GUC parameter
elog() numbers now start at 10
Add test to print error message if older elog() values are passed to elog()
Bootstrap mode now has a -d that requires an argument, like postmaster
2002-03-02 22:39:36 +01:00
|
|
|
elog(LOG, "CURRENT LOCALE ENVIRONMENT:\n\nLANG: \t%s\nLC_CTYPE:\t%s\nLC_NUMERIC:\t%s\nLC_TIME:\t%s\nLC_COLLATE:\t%s\nLC_MONETARY:\t%s\n",
|
2000-04-12 19:17:23 +02:00
|
|
|
lc->lang,
|
|
|
|
lc->lc_ctype,
|
|
|
|
lc->lc_numeric,
|
|
|
|
lc->lc_time,
|
|
|
|
lc->lc_collate,
|
2001-09-29 23:16:30 +02:00
|
|
|
lc->lc_monetary);
|
2000-06-29 03:19:36 +02:00
|
|
|
#endif
|
2000-01-07 18:22:47 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*------
|
2000-04-12 19:17:23 +02:00
|
|
|
* Set locales via a PG_LocaleCategories struct
|
2000-11-25 23:43:08 +01:00
|
|
|
*
|
|
|
|
* NB: it would be very dangerous to set the locale values to any random
|
|
|
|
* choice of locale, since that could cause indexes to become corrupt, etc.
|
|
|
|
* Therefore this routine is NOT exported from this module. It should be
|
|
|
|
* used only to restore previous locale settings during PGLC_localeconv.
|
2000-01-07 18:22:47 +01:00
|
|
|
*------
|
|
|
|
*/
|
2000-11-25 23:43:08 +01:00
|
|
|
static void
|
2001-10-25 07:50:21 +02:00
|
|
|
PGLC_setlocale(PG_LocaleCategories *lc)
|
2000-01-07 18:22:47 +01:00
|
|
|
{
|
2000-11-25 23:43:08 +01:00
|
|
|
if (!setlocale(LC_COLLATE, lc->lc_collate))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_COLLATE=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_collate);
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!setlocale(LC_CTYPE, lc->lc_ctype))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_CTYPE=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_ctype);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
if (!setlocale(LC_NUMERIC, lc->lc_numeric))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_NUMERIC=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_numeric);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
if (!setlocale(LC_TIME, lc->lc_time))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_TIME=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_time);
|
2000-01-07 18:22:47 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!setlocale(LC_MONETARY, lc->lc_monetary))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_MONETARY=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_monetary);
|
|
|
|
|
2000-06-29 03:19:36 +02:00
|
|
|
#ifdef LC_MESSAGES
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!setlocale(LC_MESSAGES, lc->lc_messages))
|
2002-03-06 07:10:59 +01:00
|
|
|
elog(WARNING, "pg_setlocale(): 'LC_MESSAGES=%s' cannot be honored.",
|
2000-11-25 23:43:08 +01:00
|
|
|
lc->lc_messages);
|
2000-06-29 03:19:36 +02:00
|
|
|
#endif
|
2000-01-07 18:22:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*------
|
|
|
|
* Return the POSIX lconv struct (contains number/money formatting information)
|
2001-03-22 05:01:46 +01:00
|
|
|
* with locale information for all categories. Note that returned lconv
|
2000-11-25 23:43:08 +01:00
|
|
|
* does not depend on currently active category settings, but on external
|
|
|
|
* environment variables for locale.
|
2000-01-07 18:22:47 +01:00
|
|
|
*------
|
|
|
|
*/
|
|
|
|
struct lconv *
|
2000-03-18 19:57:16 +01:00
|
|
|
PGLC_localeconv(void)
|
2000-01-07 18:22:47 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
PG_LocaleCategories lc;
|
2001-09-29 23:16:30 +02:00
|
|
|
struct lconv *extlconv;
|
2000-11-25 23:43:08 +01:00
|
|
|
|
|
|
|
/* Did we do it already? */
|
2001-09-29 23:16:30 +02:00
|
|
|
if (CurrentLocaleConvValid)
|
|
|
|
return &CurrentLocaleConv;
|
2000-01-07 18:22:47 +01:00
|
|
|
|
|
|
|
/* Save current locale setting to lc */
|
2000-04-12 19:17:23 +02:00
|
|
|
PGLC_current(&lc);
|
|
|
|
|
2000-11-25 23:43:08 +01:00
|
|
|
/* Set all locale categories based on postmaster's environment vars */
|
2000-01-07 18:22:47 +01:00
|
|
|
setlocale(LC_ALL, "");
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-11-25 23:43:08 +01:00
|
|
|
/* Get formatting information for the external environment */
|
2001-09-29 23:16:30 +02:00
|
|
|
extlconv = localeconv();
|
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
/*
|
|
|
|
* Must copy all values since restoring internal settings may
|
|
|
|
* overwrite
|
|
|
|
*/
|
2001-09-29 23:16:30 +02:00
|
|
|
CurrentLocaleConv = *extlconv;
|
|
|
|
CurrentLocaleConv.currency_symbol = strdup(extlconv->currency_symbol);
|
|
|
|
CurrentLocaleConv.decimal_point = strdup(extlconv->decimal_point);
|
|
|
|
CurrentLocaleConv.grouping = strdup(extlconv->grouping);
|
|
|
|
CurrentLocaleConv.thousands_sep = strdup(extlconv->thousands_sep);
|
|
|
|
CurrentLocaleConv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
|
|
|
|
CurrentLocaleConv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
|
|
|
|
CurrentLocaleConv.mon_grouping = strdup(extlconv->mon_grouping);
|
|
|
|
CurrentLocaleConv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
|
|
|
|
CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
|
|
|
|
CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-11-25 23:43:08 +01:00
|
|
|
/* Restore Postgres' internal locale settings */
|
2000-01-07 18:22:47 +01:00
|
|
|
PGLC_setlocale(&lc);
|
|
|
|
|
2001-09-29 23:16:30 +02:00
|
|
|
/* Deallocate category settings allocated in PGLC_current() */
|
|
|
|
PGLC_free_categories(&lc);
|
|
|
|
|
|
|
|
CurrentLocaleConvValid = true;
|
|
|
|
return &CurrentLocaleConv;
|
2000-01-07 18:22:47 +01:00
|
|
|
}
|
2001-10-28 07:26:15 +01:00
|
|
|
|
2001-11-05 18:46:40 +01:00
|
|
|
#endif /* USE_LOCALE */
|