|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* PostgreSQL locale utilities
|
|
|
|
*
|
|
|
|
* src/include/utils/pg_locale.h
|
|
|
|
*
|
|
|
|
* Copyright (c) 2002-2017, PostgreSQL Global Development Group
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _PG_LOCALE_
|
|
|
|
#define _PG_LOCALE_
|
|
|
|
|
Cope if platform declares mbstowcs_l(), but not locale_t, in <xlocale.h>.
Previously, we included <xlocale.h> only if necessary to get the definition
of type locale_t. According to notes in PGAC_TYPE_LOCALE_T, this is
important because on some versions of glibc that file supplies an
incompatible declaration of locale_t. (This info may be obsolete, because
on my RHEL6 box that seems to be the *only* definition of locale_t; but
there may still be glibc's in the wild for which it's a live concern.)
It turns out though that on FreeBSD and maybe other BSDen, you can get
locale_t from stdlib.h or locale.h but mbstowcs_l() and friends only from
<xlocale.h>. This was leaving us compiling calls to mbstowcs_l() and
friends with no visible prototype, which causes a warning and could
possibly cause actual trouble, since it's not declared to return int.
Hence, adjust the configure checks so that we'll include <xlocale.h>
either if it's necessary to get type locale_t or if it's necessary to
get a declaration of mbstowcs_l().
Report and patch by Aleksander Alekseev, somewhat whacked around by me.
Back-patch to all supported branches, since we have been using
mbstowcs_l() since 9.1.
10 years ago
|
|
|
#if defined(LOCALE_T_IN_XLOCALE) || defined(WCSTOMBS_L_IN_XLOCALE)
|
|
|
|
#include <xlocale.h>
|
|
|
|
#endif
|
|
|
|
#ifdef USE_ICU
|
|
|
|
#include <unicode/ucol.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "utils/guc.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* GUC settings */
|
|
|
|
extern char *locale_messages;
|
|
|
|
extern char *locale_monetary;
|
|
|
|
extern char *locale_numeric;
|
|
|
|
extern char *locale_time;
|
|
|
|
|
|
|
|
/* lc_time localization cache */
|
|
|
|
extern char *localized_abbrev_days[];
|
|
|
|
extern char *localized_full_days[];
|
|
|
|
extern char *localized_abbrev_months[];
|
|
|
|
extern char *localized_full_months[];
|
|
|
|
|
|
|
|
|
|
|
|
extern bool check_locale_messages(char **newval, void **extra, GucSource source);
|
|
|
|
extern void assign_locale_messages(const char *newval, void *extra);
|
|
|
|
extern bool check_locale_monetary(char **newval, void **extra, GucSource source);
|
|
|
|
extern void assign_locale_monetary(const char *newval, void *extra);
|
|
|
|
extern bool check_locale_numeric(char **newval, void **extra, GucSource source);
|
|
|
|
extern void assign_locale_numeric(const char *newval, void *extra);
|
|
|
|
extern bool check_locale_time(char **newval, void **extra, GucSource source);
|
|
|
|
extern void assign_locale_time(const char *newval, void *extra);
|
|
|
|
|
Replace empty locale name with implied value in CREATE DATABASE and initdb.
setlocale() accepts locale name "" as meaning "the locale specified by the
process's environment variables". Historically we've accepted that for
Postgres' locale settings, too. However, it's fairly unsafe to store an
empty string in a new database's pg_database.datcollate or datctype fields,
because then the interpretation could vary across postmaster restarts,
possibly resulting in index corruption and other unpleasantness.
Instead, we should expand "" to whatever it means at the moment of calling
CREATE DATABASE, which we can do by saving the value returned by
setlocale().
For consistency, make initdb set up the initial lc_xxx parameter values the
same way. initdb was already doing the right thing for empty locale names,
but it did not replace non-empty names with setlocale results. On a
platform where setlocale chooses to canonicalize the spellings of locale
names, this would result in annoying inconsistency. (It seems that popular
implementations of setlocale don't do such canonicalization, which is a
pity, but the POSIX spec certainly allows it to be done.) The same risk
of inconsistency leads me to not venture back-patching this, although it
could certainly be seen as a longstanding bug.
Per report from Jeff Davis, though this is not his proposed patch.
14 years ago
|
|
|
extern bool check_locale(int category, const char *locale, char **canonname);
|
|
|
|
extern char *pg_perm_setlocale(int category, const char *locale);
|
|
|
|
extern void check_strxfrm_bug(void);
|
|
|
|
|
|
|
|
extern bool lc_collate_is_c(Oid collation);
|
|
|
|
extern bool lc_ctype_is_c(Oid collation);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the POSIX lconv struct (contains number/money formatting
|
|
|
|
* information) with locale information for all categories.
|
|
|
|
*/
|
|
|
|
extern struct lconv *PGLC_localeconv(void);
|
|
|
|
|
|
|
|
extern void cache_locale_time(void);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We define our own wrapper around locale_t so we can keep the same
|
|
|
|
* function signatures for all builds, while not having to create a
|
|
|
|
* fake version of the standard type locale_t in the global namespace.
|
|
|
|
* pg_locale_t is occasionally checked for truth, so make it a pointer.
|
|
|
|
*/
|
|
|
|
struct pg_locale_t
|
|
|
|
{
|
|
|
|
char provider;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LOCALE_T
|
|
|
|
locale_t lt;
|
|
|
|
#endif
|
|
|
|
#ifdef USE_ICU
|
|
|
|
struct {
|
|
|
|
const char *locale;
|
|
|
|
UCollator *ucol;
|
|
|
|
} icu;
|
|
|
|
#endif
|
|
|
|
} info;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct pg_locale_t *pg_locale_t;
|
|
|
|
|
|
|
|
extern pg_locale_t pg_newlocale_from_collation(Oid collid);
|
|
|
|
|
|
|
|
extern char *get_collation_actual_version(char collprovider, const char *collcollate);
|
|
|
|
|
|
|
|
#ifdef USE_ICU
|
|
|
|
extern int32_t icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes);
|
|
|
|
extern int32_t icu_from_uchar(char **result, UChar *buff_uchar, int32_t len_uchar);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* These functions convert from/to libc's wchar_t, *not* pg_wchar_t */
|
|
|
|
#ifdef USE_WIDE_UPPER_LOWER
|
|
|
|
extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen,
|
|
|
|
pg_locale_t locale);
|
|
|
|
extern size_t char2wchar(wchar_t *to, size_t tolen,
|
|
|
|
const char *from, size_t fromlen, pg_locale_t locale);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* _PG_LOCALE_ */
|