aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/pg_locale.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2002-04-03 05:39:33 +0000
committerPeter Eisentraut <peter_e@gmx.net>2002-04-03 05:39:33 +0000
commit867901db9efbdae05270931daeb92042dc285710 (patch)
tree3a6541fd7908d5ca085d86fae60827efd8a4c847 /src/backend/utils/adt/pg_locale.c
parent3d7755c8e939ab9e8315fea297ee6aadcd6ad656 (diff)
downloadpostgresql-867901db9efbdae05270931daeb92042dc285710.tar.gz
postgresql-867901db9efbdae05270931daeb92042dc285710.zip
Locale support is on by default. The choice of locale is done in initdb
and/or with GUC variables.
Diffstat (limited to 'src/backend/utils/adt/pg_locale.c')
-rw-r--r--src/backend/utils/adt/pg_locale.c223
1 files changed, 93 insertions, 130 deletions
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 2c86ff5bcf1..c5c8d312d3f 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -1,173 +1,144 @@
-/* -----------------------------------------------------------------------
- * pg_locale.c
+/*-----------------------------------------------------------------------
*
- * The PostgreSQL locale utils.
+ * PostgreSQL locale utilities
*
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.16 2002/04/03 05:39:31 petere Exp $
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.15 2002/03/06 06:10:14 momjian Exp $
+ * Portions Copyright (c) 2002, PostgreSQL Global Development Group
*
- * Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
- *
- * Karel Zak
- *
- * -----------------------------------------------------------------------
+ *-----------------------------------------------------------------------
*/
#include "postgres.h"
-
-#ifdef USE_LOCALE
-
-#include <locale.h>
-
#include "utils/pg_locale.h"
-
-/* #define DEBUG_LOCALE_UTILS */
+#include <locale.h>
-static bool CurrentLocaleConvValid = false;
-static struct lconv CurrentLocaleConv;
+/* GUC storage area */
+char * locale_messages;
+char * locale_monetary;
+char * locale_numeric;
+char * locale_time;
-static void PGLC_setlocale(PG_LocaleCategories *lc);
+/* GUC parse hooks */
-/*------
- * Frees memory used in PG_LocaleCategories -- this memory is
- * allocated in PGLC_current().
- *------
- */
-void
-PGLC_free_categories(PG_LocaleCategories *lc)
+bool locale_messages_check(const char *proposed)
{
- 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);
- pfree(lc->lc_monetary);
#ifdef LC_MESSAGES
- if (lc->lc_messages)
- pfree(lc->lc_messages);
+ return chklocale(LC_MESSAGES, proposed);
+#else
+ /* We return true here so LC_MESSAGES can be set in the
+ configuration file on every system. */
+ return true;
#endif
}
-/*------
- * Return in PG_LocaleCategories the current locale settings.
- *
- * NB: strings are allocated in the current memory context!
- *------
- */
-void
-PGLC_current(PG_LocaleCategories *lc)
+bool locale_monetary_check(const char *proposed)
{
- lc->lang = getenv("LANG");
+ return chklocale(LC_MONETARY, proposed);
+}
- 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));
-#ifdef LC_MESSAGES
- lc->lc_messages = pstrdup(setlocale(LC_MESSAGES, NULL));
-#endif
+bool locale_numeric_check(const char *proposed)
+{
+ return chklocale(LC_NUMERIC, proposed);
}
+bool locale_time_check(const char *proposed)
+{
+ return chklocale(LC_TIME, proposed);
+}
-#ifdef DEBUG_LOCALE_UTILS
+/* GUC assign hooks */
-/*------
- * Print a PG_LocaleCategories struct as DEBUG
- *------
- */
-static void
-PGLC_debug_lc(PG_LocaleCategories *lc)
+void locale_messages_assign(const char *value)
{
#ifdef LC_MESSAGES
- 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",
- lc->lang,
- lc->lc_ctype,
- lc->lc_numeric,
- lc->lc_time,
- lc->lc_collate,
- lc->lc_monetary,
- lc->lc_messages);
-#else
- 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",
- lc->lang,
- lc->lc_ctype,
- lc->lc_numeric,
- lc->lc_time,
- lc->lc_collate,
- lc->lc_monetary);
+ setlocale(LC_MESSAGES, value);
#endif
}
-#endif
-/*------
- * Set locales via a PG_LocaleCategories struct
- *
- * 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.
- *------
+void locale_monetary_assign(const char *value)
+{
+ setlocale(LC_MONETARY, value);
+}
+
+void locale_numeric_assign(const char *value)
+{
+ setlocale(LC_NUMERIC, value);
+}
+
+void locale_time_assign(const char *value)
+{
+ setlocale(LC_TIME, value);
+}
+
+
+/*
+ * Returns true if the proposed string represents a valid locale of
+ * the given category. This is probably pretty slow, but it's not
+ * called in critical places.
*/
-static void
-PGLC_setlocale(PG_LocaleCategories *lc)
+bool
+chklocale(int category, const char *proposed)
{
- if (!setlocale(LC_COLLATE, lc->lc_collate))
- elog(WARNING, "pg_setlocale(): 'LC_COLLATE=%s' cannot be honored.",
- lc->lc_collate);
+ char *save;
- if (!setlocale(LC_CTYPE, lc->lc_ctype))
- elog(WARNING, "pg_setlocale(): 'LC_CTYPE=%s' cannot be honored.",
- lc->lc_ctype);
+ save = setlocale(category, NULL);
+ if (!save)
+ return false;
- if (!setlocale(LC_NUMERIC, lc->lc_numeric))
- elog(WARNING, "pg_setlocale(): 'LC_NUMERIC=%s' cannot be honored.",
- lc->lc_numeric);
+ if (!setlocale(category, proposed))
+ return false;
- if (!setlocale(LC_TIME, lc->lc_time))
- elog(WARNING, "pg_setlocale(): 'LC_TIME=%s' cannot be honored.",
- lc->lc_time);
+ setlocale(category, save);
+ return true;
+}
- if (!setlocale(LC_MONETARY, lc->lc_monetary))
- elog(WARNING, "pg_setlocale(): 'LC_MONETARY=%s' cannot be honored.",
- lc->lc_monetary);
-#ifdef LC_MESSAGES
- if (!setlocale(LC_MESSAGES, lc->lc_messages))
- elog(WARNING, "pg_setlocale(): 'LC_MESSAGES=%s' cannot be honored.",
- lc->lc_messages);
-#endif
+/*
+ * We'd like to cache whether LC_COLLATE is C (or POSIX), so we can
+ * optimize a few code paths in various places.
+ */
+bool
+lc_collate_is_c(void)
+{
+ /* Cache result so we only have to compute it once */
+ static int result = -1;
+ char *localeptr;
+
+ if (result >= 0)
+ return (bool) result;
+ localeptr = setlocale(LC_COLLATE, NULL);
+ if (!localeptr)
+ elog(PANIC, "Invalid LC_COLLATE setting");
+
+ if (strcmp(localeptr, "C") == 0)
+ result = true;
+ else if (strcmp(localeptr, "POSIX") == 0)
+ result = true;
+ else
+ result = false;
+ return (bool) result;
}
-/*------
- * Return the POSIX lconv struct (contains number/money formatting information)
- * with locale information for all categories. Note that returned lconv
- * does not depend on currently active category settings, but on external
- * environment variables for locale.
- *------
+
+
+/*
+ * Return the POSIX lconv struct (contains number/money formatting
+ * information) with locale information for all categories.
*/
struct lconv *
PGLC_localeconv(void)
{
- PG_LocaleCategories lc;
struct lconv *extlconv;
+ static bool CurrentLocaleConvValid = false;
+ static struct lconv CurrentLocaleConv;
/* Did we do it already? */
if (CurrentLocaleConvValid)
return &CurrentLocaleConv;
- /* Save current locale setting to lc */
- PGLC_current(&lc);
-
- /* Set all locale categories based on postmaster's environment vars */
- setlocale(LC_ALL, "");
-
/* Get formatting information for the external environment */
extlconv = localeconv();
@@ -187,14 +158,6 @@ PGLC_localeconv(void)
CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
- /* Restore Postgres' internal locale settings */
- PGLC_setlocale(&lc);
-
- /* Deallocate category settings allocated in PGLC_current() */
- PGLC_free_categories(&lc);
-
CurrentLocaleConvValid = true;
return &CurrentLocaleConv;
}
-
-#endif /* USE_LOCALE */