PostgreSQL Source Code  git master
pg_locale.h File Reference
#include "utils/guc.h"
Include dependency graph for pg_locale.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pg_locale_struct
 

Macros

#define LOCALE_NAME_BUFLEN   128
 

Typedefs

typedef struct pg_locale_structpg_locale_t
 

Functions

bool check_locale_messages (char **newval, void **extra, GucSource source)
 
void assign_locale_messages (const char *newval, void *extra)
 
bool check_locale_monetary (char **newval, void **extra, GucSource source)
 
void assign_locale_monetary (const char *newval, void *extra)
 
bool check_locale_numeric (char **newval, void **extra, GucSource source)
 
void assign_locale_numeric (const char *newval, void *extra)
 
bool check_locale_time (char **newval, void **extra, GucSource source)
 
void assign_locale_time (const char *newval, void *extra)
 
bool check_locale (int category, const char *locale, char **canonname)
 
char * pg_perm_setlocale (int category, const char *locale)
 
void check_strxfrm_bug (void)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
struct lconv * PGLC_localeconv (void)
 
void cache_locale_time (void)
 
void make_icu_collator (const char *iculocstr, struct pg_locale_struct *resultp)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
void check_icu_locale (const char *icu_locale)
 
size_t wchar2char (char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
 
size_t char2wchar (wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
 

Variables

PGDLLIMPORT char * locale_messages
 
PGDLLIMPORT char * locale_monetary
 
PGDLLIMPORT char * locale_numeric
 
PGDLLIMPORT char * locale_time
 
PGDLLIMPORT char * localized_abbrev_days []
 
PGDLLIMPORT char * localized_full_days []
 
PGDLLIMPORT char * localized_abbrev_months []
 
PGDLLIMPORT char * localized_full_months []
 
PGDLLIMPORT struct pg_locale_struct default_locale
 

Macro Definition Documentation

◆ LOCALE_NAME_BUFLEN

#define LOCALE_NAME_BUFLEN   128

Definition at line 38 of file pg_locale.h.

Typedef Documentation

◆ pg_locale_t

typedef struct pg_locale_struct* pg_locale_t

Definition at line 104 of file pg_locale.h.

Function Documentation

◆ assign_locale_messages()

void assign_locale_messages ( const char *  newval,
void *  extra 
)

Definition at line 358 of file pg_locale.c.

359 {
360  /*
361  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
362  * We ignore failure, as per comment above.
363  */
364 #ifdef LC_MESSAGES
365  (void) pg_perm_setlocale(LC_MESSAGES, newval);
366 #endif
367 }
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:143

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

void assign_locale_monetary ( const char *  newval,
void *  extra 
)

Definition at line 295 of file pg_locale.c.

296 {
297  CurrentLocaleConvValid = false;
298 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:103

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

void assign_locale_numeric ( const char *  newval,
void *  extra 
)

Definition at line 307 of file pg_locale.c.

308 {
309  CurrentLocaleConvValid = false;
310 }

References CurrentLocaleConvValid.

◆ assign_locale_time()

void assign_locale_time ( const char *  newval,
void *  extra 
)

Definition at line 319 of file pg_locale.c.

320 {
321  CurrentLCTimeValid = false;
322 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:104

References CurrentLCTimeValid.

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 737 of file pg_locale.c.

738 {
739  char buf[(2 * 7 + 2 * 12) * MAX_L10N_DATA];
740  char *bufptr;
741  time_t timenow;
742  struct tm *timeinfo;
743  bool strftimefail = false;
744  int encoding;
745  int i;
746  char *save_lc_time;
747 #ifdef WIN32
748  char *save_lc_ctype;
749 #endif
750 
751  /* did we do this already? */
752  if (CurrentLCTimeValid)
753  return;
754 
755  elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
756 
757  /*
758  * As in PGLC_localeconv(), it's critical that we not throw error while
759  * libc's locale settings have nondefault values. Hence, we just call
760  * strftime() within the critical section, and then convert and save its
761  * results afterwards.
762  */
763 
764  /* Save prevailing value of time locale */
765  save_lc_time = setlocale(LC_TIME, NULL);
766  if (!save_lc_time)
767  elog(ERROR, "setlocale(NULL) failed");
768  save_lc_time = pstrdup(save_lc_time);
769 
770 #ifdef WIN32
771 
772  /*
773  * On Windows, it appears that wcsftime() internally uses LC_CTYPE, so we
774  * must set it here. This code looks the same as what PGLC_localeconv()
775  * does, but the underlying reason is different: this does NOT determine
776  * the encoding we'll get back from strftime_win32().
777  */
778 
779  /* Save prevailing value of ctype locale */
780  save_lc_ctype = setlocale(LC_CTYPE, NULL);
781  if (!save_lc_ctype)
782  elog(ERROR, "setlocale(NULL) failed");
783  save_lc_ctype = pstrdup(save_lc_ctype);
784 
785  /* use lc_time to set the ctype */
786  setlocale(LC_CTYPE, locale_time);
787 #endif
788 
789  setlocale(LC_TIME, locale_time);
790 
791  /* We use times close to current time as data for strftime(). */
792  timenow = time(NULL);
793  timeinfo = localtime(&timenow);
794 
795  /* Store the strftime results in MAX_L10N_DATA-sized portions of buf[] */
796  bufptr = buf;
797 
798  /*
799  * MAX_L10N_DATA is sufficient buffer space for every known locale, and
800  * POSIX defines no strftime() errors. (Buffer space exhaustion is not an
801  * error.) An implementation might report errors (e.g. ENOMEM) by
802  * returning 0 (or, less plausibly, a negative value) and setting errno.
803  * Report errno just in case the implementation did that, but clear it in
804  * advance of the calls so we don't emit a stale, unrelated errno.
805  */
806  errno = 0;
807 
808  /* localized days */
809  for (i = 0; i < 7; i++)
810  {
811  timeinfo->tm_wday = i;
812  if (strftime(bufptr, MAX_L10N_DATA, "%a", timeinfo) <= 0)
813  strftimefail = true;
814  bufptr += MAX_L10N_DATA;
815  if (strftime(bufptr, MAX_L10N_DATA, "%A", timeinfo) <= 0)
816  strftimefail = true;
817  bufptr += MAX_L10N_DATA;
818  }
819 
820  /* localized months */
821  for (i = 0; i < 12; i++)
822  {
823  timeinfo->tm_mon = i;
824  timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
825  if (strftime(bufptr, MAX_L10N_DATA, "%b", timeinfo) <= 0)
826  strftimefail = true;
827  bufptr += MAX_L10N_DATA;
828  if (strftime(bufptr, MAX_L10N_DATA, "%B", timeinfo) <= 0)
829  strftimefail = true;
830  bufptr += MAX_L10N_DATA;
831  }
832 
833  /*
834  * Restore the prevailing locale settings; as in PGLC_localeconv(),
835  * failure to do so is fatal.
836  */
837 #ifdef WIN32
838  if (!setlocale(LC_CTYPE, save_lc_ctype))
839  elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype);
840 #endif
841  if (!setlocale(LC_TIME, save_lc_time))
842  elog(FATAL, "failed to restore LC_TIME to \"%s\"", save_lc_time);
843 
844  /*
845  * At this point we've done our best to clean up, and can throw errors, or
846  * call functions that might throw errors, with a clean conscience.
847  */
848  if (strftimefail)
849  elog(ERROR, "strftime() failed: %m");
850 
851  /* Release the pstrdup'd locale names */
852  pfree(save_lc_time);
853 #ifdef WIN32
854  pfree(save_lc_ctype);
855 #endif
856 
857 #ifndef WIN32
858 
859  /*
860  * As in PGLC_localeconv(), we must convert strftime()'s output from the
861  * encoding implied by LC_TIME to the database encoding. If we can't
862  * identify the LC_TIME encoding, just perform encoding validation.
863  */
865  if (encoding < 0)
867 
868 #else
869 
870  /*
871  * On Windows, strftime_win32() always returns UTF8 data, so convert from
872  * that if necessary.
873  */
874  encoding = PG_UTF8;
875 
876 #endif /* WIN32 */
877 
878  bufptr = buf;
879 
880  /* localized days */
881  for (i = 0; i < 7; i++)
882  {
884  bufptr += MAX_L10N_DATA;
886  bufptr += MAX_L10N_DATA;
887  }
888  localized_abbrev_days[7] = NULL;
889  localized_full_days[7] = NULL;
890 
891  /* localized months */
892  for (i = 0; i < 12; i++)
893  {
895  bufptr += MAX_L10N_DATA;
897  bufptr += MAX_L10N_DATA;
898  }
899  localized_abbrev_months[12] = NULL;
900  localized_full_months[12] = NULL;
901 
902  CurrentLCTimeValid = true;
903 }
#define DEBUG3
Definition: elog.h:22
#define FATAL
Definition: elog.h:35
#define ERROR
Definition: elog.h:33
int i
Definition: isn.c:73
static struct pg_tm tm
Definition: localtime.c:102
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void pfree(void *pointer)
Definition: mcxt.c:1175
int32 encoding
Definition: pg_database.h:41
char * localized_full_months[12+1]
Definition: pg_locale.c:100
char * locale_time
Definition: pg_locale.c:88
static void cache_single_string(char **dst, const char *src, int encoding)
Definition: pg_locale.c:714
#define MAX_L10N_DATA
Definition: pg_locale.c:81
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:99
char * localized_full_days[7+1]
Definition: pg_locale.c:98
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:97
static char * buf
Definition: pg_test_fsync.c:67
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
@ PG_UTF8
Definition: pg_wchar.h:230
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:451
#define setlocale(a, b)
Definition: win32_port.h:446

References buf, cache_single_string(), CurrentLCTimeValid, DEBUG3, elog(), encoding, ERROR, FATAL, i, locale_time, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, MAX_L10N_DATA, pfree(), pg_get_encoding_from_locale(), PG_SQL_ASCII, PG_UTF8, pstrdup(), setlocale, and tm.

Referenced by DCH_from_char(), and DCH_to_char().

◆ char2wchar()

size_t char2wchar ( wchar_t *  to,
size_t  tolen,
const char *  from,
size_t  fromlen,
pg_locale_t  locale 
)

Definition at line 2088 of file pg_locale.c.

2090 {
2091  size_t result;
2092 
2093  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2094 
2095  if (tolen == 0)
2096  return 0;
2097 
2098 #ifdef WIN32
2099  /* See WIN32 "Unicode" comment above */
2100  if (GetDatabaseEncoding() == PG_UTF8)
2101  {
2102  /* Win32 API does not work for zero-length input */
2103  if (fromlen == 0)
2104  result = 0;
2105  else
2106  {
2107  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
2108  /* A zero return is failure */
2109  if (result == 0)
2110  result = -1;
2111  }
2112 
2113  if (result != -1)
2114  {
2115  Assert(result < tolen);
2116  /* Append trailing null wchar (MultiByteToWideChar() does not) */
2117  to[result] = 0;
2118  }
2119  }
2120  else
2121 #endif /* WIN32 */
2122  {
2123  /* mbstowcs requires ending '\0' */
2124  char *str = pnstrdup(from, fromlen);
2125 
2126  if (locale == (pg_locale_t) 0)
2127  {
2128  /* Use mbstowcs directly for the default locale */
2129  result = mbstowcs(to, str, tolen);
2130  }
2131  else
2132  {
2133 #ifdef HAVE_LOCALE_T
2134 #ifdef HAVE_MBSTOWCS_L
2135  /* Use mbstowcs_l for nondefault locales */
2136  result = mbstowcs_l(to, str, tolen, locale->info.lt);
2137 #else /* !HAVE_MBSTOWCS_L */
2138  /* We have to temporarily set the locale as current ... ugh */
2139  locale_t save_locale = uselocale(locale->info.lt);
2140 
2141  result = mbstowcs(to, str, tolen);
2142 
2143  uselocale(save_locale);
2144 #endif /* HAVE_MBSTOWCS_L */
2145 #else /* !HAVE_LOCALE_T */
2146  /* Can't have locale != 0 without HAVE_LOCALE_T */
2147  elog(ERROR, "mbstowcs_l is not available");
2148  result = 0; /* keep compiler quiet */
2149 #endif /* HAVE_LOCALE_T */
2150  }
2151 
2152  pfree(str);
2153  }
2154 
2155  if (result == -1)
2156  {
2157  /*
2158  * Invalid multibyte character encountered. We try to give a useful
2159  * error message by letting pg_verifymbstr check the string. But it's
2160  * possible that the string is OK to us, and not OK to mbstowcs ---
2161  * this suggests that the LC_CTYPE locale is different from the
2162  * database encoding. Give a generic error message if pg_verifymbstr
2163  * can't find anything wrong.
2164  */
2165  pg_verifymbstr(from, fromlen, false); /* might not return */
2166  /* but if it does ... */
2167  ereport(ERROR,
2168  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
2169  errmsg("invalid multibyte character for locale"),
2170  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
2171  }
2172 
2173  return result;
2174 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ereport(elevel,...)
Definition: elog.h:143
static char * locale
Definition: initdb.c:128
Assert(fmt[strlen(fmt) - 1] !='\n')
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1505
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1316
#define locale_t
Definition: win32_port.h:401
#define mbstowcs_l
Definition: win32_port.h:428

References Assert(), elog(), ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), locale, locale_t, mbstowcs_l, pfree(), PG_UTF8, pg_verifymbstr(), pnstrdup(), and generate_unaccent_rules::str.

Referenced by lowerstr_with_len(), str_initcap(), str_tolower(), str_toupper(), t_isalpha(), t_isdigit(), t_isprint(), t_isspace(), and TParserInit().

◆ check_icu_locale()

void check_icu_locale ( const char *  icu_locale)

Definition at line 1981 of file pg_locale.c.

1982 {
1983 #ifdef USE_ICU
1984  UCollator *collator;
1985  UErrorCode status;
1986 
1987  status = U_ZERO_ERROR;
1988  collator = ucol_open(icu_locale, &status);
1989  if (U_FAILURE(status))
1990  ereport(ERROR,
1991  (errmsg("could not open collator for locale \"%s\": %s",
1992  icu_locale, u_errorName(status))));
1993 
1994  if (U_ICU_VERSION_MAJOR_NUM < 54)
1995  icu_set_collation_attributes(collator, icu_locale);
1996  ucol_close(collator);
1997 #else
1998  ereport(ERROR,
1999  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2000  errmsg("ICU is not supported in this build")));
2001 #endif
2002 }
static char * icu_locale
Definition: initdb.c:136
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229

References ereport, errcode(), errmsg(), ERROR, icu_locale, and status().

Referenced by createdb().

◆ check_locale()

bool check_locale ( int  category,
const char *  locale,
char **  canonname 
)

Definition at line 246 of file pg_locale.c.

247 {
248  char *save;
249  char *res;
250 
251  if (canonname)
252  *canonname = NULL; /* in case of failure */
253 
254  save = setlocale(category, NULL);
255  if (!save)
256  return false; /* won't happen, we hope */
257 
258  /* save may be pointing at a modifiable scratch variable, see above. */
259  save = pstrdup(save);
260 
261  /* set the locale with setlocale, to see if it accepts it. */
262  res = setlocale(category, locale);
263 
264  /* save canonical name if requested. */
265  if (res && canonname)
266  *canonname = pstrdup(res);
267 
268  /* restore old value. */
269  if (!setlocale(category, save))
270  elog(WARNING, "failed to restore old locale \"%s\"", save);
271  pfree(save);
272 
273  return (res != NULL);
274 }
#define WARNING
Definition: elog.h:30

References elog(), locale, pfree(), pstrdup(), res, setlocale, and WARNING.

Referenced by check_locale_messages(), check_locale_monetary(), check_locale_numeric(), check_locale_time(), and createdb().

◆ check_locale_messages()

bool check_locale_messages ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 335 of file pg_locale.c.

336 {
337  if (**newval == '\0')
338  {
339  if (source == PGC_S_DEFAULT)
340  return true;
341  else
342  return false;
343  }
344 
345  /*
346  * LC_MESSAGES category does not exist everywhere, but accept it anyway
347  *
348  * On Windows, we can't even check the value, so accept blindly
349  */
350 #if defined(LC_MESSAGES) && !defined(WIN32)
351  return check_locale(LC_MESSAGES, *newval, NULL);
352 #else
353  return true;
354 #endif
355 }
@ PGC_S_DEFAULT
Definition: guc.h:110
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:246
static rewind_source * source
Definition: pg_rewind.c:81

References check_locale(), newval, PGC_S_DEFAULT, and source.

◆ check_locale_monetary()

bool check_locale_monetary ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 289 of file pg_locale.c.

290 {
291  return check_locale(LC_MONETARY, *newval, NULL);
292 }

References check_locale(), and newval.

◆ check_locale_numeric()

bool check_locale_numeric ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 301 of file pg_locale.c.

302 {
303  return check_locale(LC_NUMERIC, *newval, NULL);
304 }

References check_locale(), and newval.

◆ check_locale_time()

bool check_locale_time ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 313 of file pg_locale.c.

314 {
315  return check_locale(LC_TIME, *newval, NULL);
316 }

References check_locale(), and newval.

◆ check_strxfrm_bug()

void check_strxfrm_bug ( void  )

Definition at line 1177 of file pg_locale.c.

1178 {
1179  char buf[32];
1180  const int canary = 0x7F;
1181  bool ok = true;
1182 
1183  /*
1184  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1185  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1186  * below that range.
1187  *
1188  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1189  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1190  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1191  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1192  */
1193  buf[7] = canary;
1194  (void) strxfrm(buf, "ab", 7);
1195  if (buf[7] != canary)
1196  ok = false;
1197 
1198  /*
1199  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1200  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1201  * affected systems ignore the length limit and modify a number of bytes
1202  * one less than the return value. The problem inputs for this bug do not
1203  * overlap those for the Solaris bug, hence a distinct test.
1204  *
1205  * Affected systems include smartos-20110926T021612Z. Affected locales
1206  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1207  */
1208  buf[1] = canary;
1209  (void) strxfrm(buf, "a", 1);
1210  if (buf[1] != canary)
1211  ok = false;
1212 
1213  if (!ok)
1214  ereport(ERROR,
1215  (errcode(ERRCODE_SYSTEM_ERROR),
1216  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1217  setlocale(LC_COLLATE, NULL)),
1218  errhint("Apply system library package updates.")));
1219 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:991

References buf, ereport, errcode(), errhint(), errmsg_internal(), ERROR, and setlocale.

Referenced by CheckMyDatabase(), and main().

◆ get_collation_actual_version()

char* get_collation_actual_version ( char  collprovider,
const char *  collcollate 
)

Definition at line 1674 of file pg_locale.c.

1675 {
1676  char *collversion = NULL;
1677 
1678 #ifdef USE_ICU
1679  if (collprovider == COLLPROVIDER_ICU)
1680  {
1681  UCollator *collator;
1682  UErrorCode status;
1683  UVersionInfo versioninfo;
1684  char buf[U_MAX_VERSION_STRING_LENGTH];
1685 
1686  status = U_ZERO_ERROR;
1687  collator = ucol_open(collcollate, &status);
1688  if (U_FAILURE(status))
1689  ereport(ERROR,
1690  (errmsg("could not open collator for locale \"%s\": %s",
1691  collcollate, u_errorName(status))));
1692  ucol_getVersion(collator, versioninfo);
1693  ucol_close(collator);
1694 
1695  u_versionToString(versioninfo, buf);
1696  collversion = pstrdup(buf);
1697  }
1698  else
1699 #endif
1700  if (collprovider == COLLPROVIDER_LIBC &&
1701  pg_strcasecmp("C", collcollate) != 0 &&
1702  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1703  pg_strcasecmp("POSIX", collcollate) != 0)
1704  {
1705 #if defined(__GLIBC__)
1706  /* Use the glibc version because we don't have anything better. */
1707  collversion = pstrdup(gnu_get_libc_version());
1708 #elif defined(LC_VERSION_MASK)
1709  locale_t loc;
1710 
1711  /* Look up FreeBSD collation version. */
1712  loc = newlocale(LC_COLLATE, collcollate, NULL);
1713  if (loc)
1714  {
1715  collversion =
1716  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1717  freelocale(loc);
1718  }
1719  else
1720  ereport(ERROR,
1721  (errmsg("could not load locale \"%s\"", collcollate)));
1722 #elif defined(WIN32) && _WIN32_WINNT >= 0x0600
1723  /*
1724  * If we are targeting Windows Vista and above, we can ask for a name
1725  * given a collation name (earlier versions required a location code
1726  * that we don't have).
1727  */
1728  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1729  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1730 
1731  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1732  LOCALE_NAME_MAX_LENGTH);
1733  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1734  {
1735  /*
1736  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1737  * locale name like "English_United States.1252". Until those
1738  * values can be prevented from entering the system, or 100%
1739  * reliably converted to the more useful tag format, tolerate the
1740  * resulting error and report that we have no version data.
1741  */
1742  if (GetLastError() == ERROR_INVALID_PARAMETER)
1743  return NULL;
1744 
1745  ereport(ERROR,
1746  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1747  collcollate,
1748  GetLastError())));
1749  }
1750  collversion = psprintf("%d.%d,%d.%d",
1751  (version.dwNLSVersion >> 8) & 0xFFFF,
1752  version.dwNLSVersion & 0xFF,
1753  (version.dwDefinedVersion >> 8) & 0xFFFF,
1754  version.dwDefinedVersion & 0xFF);
1755 #endif
1756  }
1757 
1758  return collversion;
1759 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References buf, ereport, errmsg(), ERROR, locale_t, pg_strcasecmp(), pg_strncasecmp(), psprintf(), pstrdup(), and status().

Referenced by AlterCollation(), AlterDatabaseRefreshColl(), CheckMyDatabase(), createdb(), DefineCollation(), pg_collation_actual_version(), pg_database_collation_actual_version(), pg_import_system_collations(), and pg_newlocale_from_collation().

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1326 of file pg_locale.c.

1327 {
1328  /*
1329  * If we're asked about "collation 0", return false, so that the code will
1330  * go into the non-C path and report that the collation is bogus.
1331  */
1332  if (!OidIsValid(collation))
1333  return false;
1334 
1335  /*
1336  * If we're asked about the default collation, we have to inquire of the C
1337  * library. Cache the result so we only have to compute it once.
1338  */
1339  if (collation == DEFAULT_COLLATION_OID)
1340  {
1341  static int result = -1;
1342  char *localeptr;
1343 
1344  if (default_locale.provider == COLLPROVIDER_ICU)
1345  return false;
1346 
1347  if (result >= 0)
1348  return (bool) result;
1349  localeptr = setlocale(LC_COLLATE, NULL);
1350  if (!localeptr)
1351  elog(ERROR, "invalid LC_COLLATE setting");
1352 
1353  if (strcmp(localeptr, "C") == 0)
1354  result = true;
1355  else if (strcmp(localeptr, "POSIX") == 0)
1356  result = true;
1357  else
1358  result = false;
1359  return (bool) result;
1360  }
1361 
1362  /*
1363  * If we're asked about the built-in C/POSIX collations, we know that.
1364  */
1365  if (collation == C_COLLATION_OID ||
1366  collation == POSIX_COLLATION_OID)
1367  return true;
1368 
1369  /*
1370  * Otherwise, we have to consult pg_collation, but we cache that.
1371  */
1372  return (lookup_collation_cache(collation, true))->collate_is_c;
1373 }
#define OidIsValid(objectId)
Definition: c.h:721
struct pg_locale_struct default_locale
Definition: pg_locale.c:1428
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1247

References default_locale, elog(), ERROR, lookup_collation_cache(), OidIsValid, pg_locale_struct::provider, and setlocale.

Referenced by bpchareq(), bpcharne(), btvarstrequalimage(), convert_string_datum(), DefineCollation(), hashbpchar(), hashbpcharextended(), hashtext(), hashtextextended(), make_greater_string(), match_pattern_prefix(), spg_text_inner_consistent(), text_position_setup(), text_starts_with(), texteq(), textne(), varstr_cmp(), and varstr_sortsupport().

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1379 of file pg_locale.c.

1380 {
1381  /*
1382  * If we're asked about "collation 0", return false, so that the code will
1383  * go into the non-C path and report that the collation is bogus.
1384  */
1385  if (!OidIsValid(collation))
1386  return false;
1387 
1388  /*
1389  * If we're asked about the default collation, we have to inquire of the C
1390  * library. Cache the result so we only have to compute it once.
1391  */
1392  if (collation == DEFAULT_COLLATION_OID)
1393  {
1394  static int result = -1;
1395  char *localeptr;
1396 
1397  if (default_locale.provider == COLLPROVIDER_ICU)
1398  return false;
1399 
1400  if (result >= 0)
1401  return (bool) result;
1402  localeptr = setlocale(LC_CTYPE, NULL);
1403  if (!localeptr)
1404  elog(ERROR, "invalid LC_CTYPE setting");
1405 
1406  if (strcmp(localeptr, "C") == 0)
1407  result = true;
1408  else if (strcmp(localeptr, "POSIX") == 0)
1409  result = true;
1410  else
1411  result = false;
1412  return (bool) result;
1413  }
1414 
1415  /*
1416  * If we're asked about the built-in C/POSIX collations, we know that.
1417  */
1418  if (collation == C_COLLATION_OID ||
1419  collation == POSIX_COLLATION_OID)
1420  return true;
1421 
1422  /*
1423  * Otherwise, we have to consult pg_collation, but we cache that.
1424  */
1425  return (lookup_collation_cache(collation, true))->ctype_is_c;
1426 }

Referenced by DefineCollation(), Generic_Text_IC_like(), GenericMatchText(), like_fixed_prefix(), lowerstr_with_len(), pg_set_regex_collation(), str_initcap(), str_tolower(), str_toupper(), t_isalpha(), t_isdigit(), t_isprint(), t_isspace(), and TParserInit().

◆ make_icu_collator()

void make_icu_collator ( const char *  iculocstr,
struct pg_locale_struct resultp 
)

Definition at line 1431 of file pg_locale.c.

1433 {
1434 #ifdef USE_ICU
1435  UCollator *collator;
1436  UErrorCode status;
1437 
1438  status = U_ZERO_ERROR;
1439  collator = ucol_open(iculocstr, &status);
1440  if (U_FAILURE(status))
1441  ereport(ERROR,
1442  (errmsg("could not open collator for locale \"%s\": %s",
1443  iculocstr, u_errorName(status))));
1444 
1445  if (U_ICU_VERSION_MAJOR_NUM < 54)
1446  icu_set_collation_attributes(collator, iculocstr);
1447 
1448  /* We will leak this string if the caller errors later :-( */
1449  resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1450  resultp->info.icu.ucol = collator;
1451 #else /* not USE_ICU */
1452  /* could get here if a collation was created by a build with ICU */
1453  ereport(ERROR,
1454  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1455  errmsg("ICU is not supported in this build")));
1456 #endif /* not USE_ICU */
1457 }
MemoryContext TopMemoryContext
Definition: mcxt.c:48
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1292
union pg_locale_struct::@150 info

References ereport, errcode(), errmsg(), ERROR, pg_locale_struct::info, MemoryContextStrdup(), status(), and TopMemoryContext.

Referenced by CheckMyDatabase(), and pg_newlocale_from_collation().

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1508 of file pg_locale.c.

1509 {
1510  collation_cache_entry *cache_entry;
1511 
1512  /* Callers must pass a valid OID */
1513  Assert(OidIsValid(collid));
1514 
1515  if (collid == DEFAULT_COLLATION_OID)
1516  {
1517  if (default_locale.provider == COLLPROVIDER_ICU)
1518  return &default_locale;
1519  else
1520  return (pg_locale_t) 0;
1521  }
1522 
1523  cache_entry = lookup_collation_cache(collid, false);
1524 
1525  if (cache_entry->locale == 0)
1526  {
1527  /* We haven't computed this yet in this session, so do it */
1528  HeapTuple tp;
1529  Form_pg_collation collform;
1530  struct pg_locale_struct result;
1531  pg_locale_t resultp;
1532  Datum datum;
1533  bool isnull;
1534 
1535  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1536  if (!HeapTupleIsValid(tp))
1537  elog(ERROR, "cache lookup failed for collation %u", collid);
1538  collform = (Form_pg_collation) GETSTRUCT(tp);
1539 
1540  /* We'll fill in the result struct locally before allocating memory */
1541  memset(&result, 0, sizeof(result));
1542  result.provider = collform->collprovider;
1543  result.deterministic = collform->collisdeterministic;
1544 
1545  if (collform->collprovider == COLLPROVIDER_LIBC)
1546  {
1547 #ifdef HAVE_LOCALE_T
1548  const char *collcollate;
1549  const char *collctype pg_attribute_unused();
1550  locale_t loc;
1551 
1552  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
1553  Assert(!isnull);
1554  collcollate = TextDatumGetCString(datum);
1555  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
1556  Assert(!isnull);
1557  collctype = TextDatumGetCString(datum);
1558 
1559  if (strcmp(collcollate, collctype) == 0)
1560  {
1561  /* Normal case where they're the same */
1562  errno = 0;
1563 #ifndef WIN32
1564  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1565  NULL);
1566 #else
1567  loc = _create_locale(LC_ALL, collcollate);
1568 #endif
1569  if (!loc)
1570  report_newlocale_failure(collcollate);
1571  }
1572  else
1573  {
1574 #ifndef WIN32
1575  /* We need two newlocale() steps */
1576  locale_t loc1;
1577 
1578  errno = 0;
1579  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1580  if (!loc1)
1581  report_newlocale_failure(collcollate);
1582  errno = 0;
1583  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1584  if (!loc)
1585  report_newlocale_failure(collctype);
1586 #else
1587 
1588  /*
1589  * XXX The _create_locale() API doesn't appear to support
1590  * this. Could perhaps be worked around by changing
1591  * pg_locale_t to contain two separate fields.
1592  */
1593  ereport(ERROR,
1594  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1595  errmsg("collations with different collate and ctype values are not supported on this platform")));
1596 #endif
1597  }
1598 
1599  result.info.lt = loc;
1600 #else /* not HAVE_LOCALE_T */
1601  /* platform that doesn't support locale_t */
1602  ereport(ERROR,
1603  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1604  errmsg("collation provider LIBC is not supported on this platform")));
1605 #endif /* not HAVE_LOCALE_T */
1606  }
1607  else if (collform->collprovider == COLLPROVIDER_ICU)
1608  {
1609  const char *iculocstr;
1610 
1611  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colliculocale, &isnull);
1612  Assert(!isnull);
1613  iculocstr = TextDatumGetCString(datum);
1614  make_icu_collator(iculocstr, &result);
1615  }
1616 
1617  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1618  &isnull);
1619  if (!isnull)
1620  {
1621  char *actual_versionstr;
1622  char *collversionstr;
1623 
1624  collversionstr = TextDatumGetCString(datum);
1625 
1626  datum = SysCacheGetAttr(COLLOID, tp, collform->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate, &isnull);
1627  Assert(!isnull);
1628 
1629  actual_versionstr = get_collation_actual_version(collform->collprovider,
1630  TextDatumGetCString(datum));
1631  if (!actual_versionstr)
1632  {
1633  /*
1634  * This could happen when specifying a version in CREATE
1635  * COLLATION but the provider does not support versioning, or
1636  * manually creating a mess in the catalogs.
1637  */
1638  ereport(ERROR,
1639  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1640  NameStr(collform->collname))));
1641  }
1642 
1643  if (strcmp(actual_versionstr, collversionstr) != 0)
1644  ereport(WARNING,
1645  (errmsg("collation \"%s\" has version mismatch",
1646  NameStr(collform->collname)),
1647  errdetail("The collation in the database was created using version %s, "
1648  "but the operating system provides version %s.",
1649  collversionstr, actual_versionstr),
1650  errhint("Rebuild all objects affected by this collation and run "
1651  "ALTER COLLATION %s REFRESH VERSION, "
1652  "or build PostgreSQL with the right library version.",
1653  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1654  NameStr(collform->collname)))));
1655  }
1656 
1657  ReleaseSysCache(tp);
1658 
1659  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1660  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1661  *resultp = result;
1662 
1663  cache_entry->locale = resultp;
1664  }
1665 
1666  return cache_entry->locale;
1667 }
#define TextDatumGetCString(d)
Definition: builtins.h:86
#define NameStr(name)
Definition: c.h:692
int errdetail(const char *fmt,...)
Definition: elog.c:1037
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
pg_attribute_unused() static bool check_table(const char *(*TABLE)[2]
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3326
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:57
void make_icu_collator(const char *iculocstr, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1431
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1674
uintptr_t Datum
Definition: postgres.h:411
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12273
Definition: pg_locale.c:109
pg_locale_t locale
Definition: pg_locale.c:114
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
@ COLLOID
Definition: syscache.h:50

References Assert(), COLLOID, default_locale, pg_locale_struct::deterministic, elog(), ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, get_collation_actual_version(), get_namespace_name(), GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, collation_cache_entry::locale, locale_t, lookup_collation_cache(), make_icu_collator(), MemoryContextAlloc(), NameStr, ObjectIdGetDatum, OidIsValid, pg_attribute_unused(), pg_locale_struct::provider, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), TextDatumGetCString, TopMemoryContext, and WARNING.

Referenced by bpchareq(), bpcharne(), DefineCollation(), Generic_Text_IC_like(), GenericMatchText(), hashbpchar(), hashbpcharextended(), hashtext(), hashtextextended(), like_fixed_prefix(), pg_set_regex_collation(), str_initcap(), str_tolower(), str_toupper(), text_position_setup(), text_starts_with(), texteq(), textne(), varstr_cmp(), and varstr_sortsupport().

◆ pg_perm_setlocale()

char* pg_perm_setlocale ( int  category,
const char *  locale 
)

Definition at line 143 of file pg_locale.c.

144 {
145  char *result;
146  const char *envvar;
147 
148 #ifndef WIN32
149  result = setlocale(category, locale);
150 #else
151 
152  /*
153  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
154  * the given value is good and set it in the environment variables. We
155  * must ignore attempts to set to "", which means "keep using the old
156  * environment value".
157  */
158 #ifdef LC_MESSAGES
159  if (category == LC_MESSAGES)
160  {
161  result = (char *) locale;
162  if (locale == NULL || locale[0] == '\0')
163  return result;
164  }
165  else
166 #endif
167  result = setlocale(category, locale);
168 #endif /* WIN32 */
169 
170  if (result == NULL)
171  return result; /* fall out immediately on failure */
172 
173  /*
174  * Use the right encoding in translated messages. Under ENABLE_NLS, let
175  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
176  * format strings are ASCII, but database-encoding strings may enter the
177  * message via %s. This makes the overall message encoding equal to the
178  * database encoding.
179  */
180  if (category == LC_CTYPE)
181  {
182  static char save_lc_ctype[LOCALE_NAME_BUFLEN];
183 
184  /* copy setlocale() return value before callee invokes it again */
185  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
186  result = save_lc_ctype;
187 
188 #ifdef ENABLE_NLS
189  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
190 #else
192 #endif
193  }
194 
195  switch (category)
196  {
197  case LC_COLLATE:
198  envvar = "LC_COLLATE";
199  break;
200  case LC_CTYPE:
201  envvar = "LC_CTYPE";
202  break;
203 #ifdef LC_MESSAGES
204  case LC_MESSAGES:
205  envvar = "LC_MESSAGES";
206 #ifdef WIN32
207  result = IsoLocaleName(locale);
208  if (result == NULL)
209  result = (char *) locale;
210  elog(DEBUG3, "IsoLocaleName() executed; locale: \"%s\"", result);
211 #endif /* WIN32 */
212  break;
213 #endif /* LC_MESSAGES */
214  case LC_MONETARY:
215  envvar = "LC_MONETARY";
216  break;
217  case LC_NUMERIC:
218  envvar = "LC_NUMERIC";
219  break;
220  case LC_TIME:
221  envvar = "LC_TIME";
222  break;
223  default:
224  elog(FATAL, "unrecognized LC category: %d", category);
225  return NULL; /* keep compiler quiet */
226  }
227 
228  if (setenv(envvar, result, 1) != 0)
229  return NULL;
230 
231  return result;
232 }
void SetMessageEncoding(int encoding)
Definition: mbutils.c:1114
#define LOCALE_NAME_BUFLEN
Definition: pg_locale.h:38
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define setenv(x, y, z)
Definition: win32_port.h:507

References DEBUG3, elog(), FATAL, GetDatabaseEncoding(), locale, LOCALE_NAME_BUFLEN, setenv, setlocale, SetMessageEncoding(), and strlcpy().

Referenced by assign_locale_messages(), CheckMyDatabase(), and init_locale().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 455 of file pg_locale.c.

456 {
457  static struct lconv CurrentLocaleConv;
458  static bool CurrentLocaleConvAllocated = false;
459  struct lconv *extlconv;
460  struct lconv worklconv;
461  char *save_lc_monetary;
462  char *save_lc_numeric;
463 #ifdef WIN32
464  char *save_lc_ctype;
465 #endif
466 
467  /* Did we do it already? */
469  return &CurrentLocaleConv;
470 
471  /* Free any already-allocated storage */
472  if (CurrentLocaleConvAllocated)
473  {
474  free_struct_lconv(&CurrentLocaleConv);
475  CurrentLocaleConvAllocated = false;
476  }
477 
478  /*
479  * This is tricky because we really don't want to risk throwing error
480  * while the locale is set to other than our usual settings. Therefore,
481  * the process is: collect the usual settings, set locale to special
482  * setting, copy relevant data into worklconv using strdup(), restore
483  * normal settings, convert data to desired encoding, and finally stash
484  * the collected data in CurrentLocaleConv. This makes it safe if we
485  * throw an error during encoding conversion or run out of memory anywhere
486  * in the process. All data pointed to by struct lconv members is
487  * allocated with strdup, to avoid premature elog(ERROR) and to allow
488  * using a single cleanup routine.
489  */
490  memset(&worklconv, 0, sizeof(worklconv));
491 
492  /* Save prevailing values of monetary and numeric locales */
493  save_lc_monetary = setlocale(LC_MONETARY, NULL);
494  if (!save_lc_monetary)
495  elog(ERROR, "setlocale(NULL) failed");
496  save_lc_monetary = pstrdup(save_lc_monetary);
497 
498  save_lc_numeric = setlocale(LC_NUMERIC, NULL);
499  if (!save_lc_numeric)
500  elog(ERROR, "setlocale(NULL) failed");
501  save_lc_numeric = pstrdup(save_lc_numeric);
502 
503 #ifdef WIN32
504 
505  /*
506  * The POSIX standard explicitly says that it is undefined what happens if
507  * LC_MONETARY or LC_NUMERIC imply an encoding (codeset) different from
508  * that implied by LC_CTYPE. In practice, all Unix-ish platforms seem to
509  * believe that localeconv() should return strings that are encoded in the
510  * codeset implied by the LC_MONETARY or LC_NUMERIC locale name. Hence,
511  * once we have successfully collected the localeconv() results, we will
512  * convert them from that codeset to the desired server encoding.
513  *
514  * Windows, of course, resolutely does things its own way; on that
515  * platform LC_CTYPE has to match LC_MONETARY/LC_NUMERIC to get sane
516  * results. Hence, we must temporarily set that category as well.
517  */
518 
519  /* Save prevailing value of ctype locale */
520  save_lc_ctype = setlocale(LC_CTYPE, NULL);
521  if (!save_lc_ctype)
522  elog(ERROR, "setlocale(NULL) failed");
523  save_lc_ctype = pstrdup(save_lc_ctype);
524 
525  /* Here begins the critical section where we must not throw error */
526 
527  /* use numeric to set the ctype */
528  setlocale(LC_CTYPE, locale_numeric);
529 #endif
530 
531  /* Get formatting information for numeric */
532  setlocale(LC_NUMERIC, locale_numeric);
533  extlconv = localeconv();
534 
535  /* Must copy data now in case setlocale() overwrites it */
536  worklconv.decimal_point = strdup(extlconv->decimal_point);
537  worklconv.thousands_sep = strdup(extlconv->thousands_sep);
538  worklconv.grouping = strdup(extlconv->grouping);
539 
540 #ifdef WIN32
541  /* use monetary to set the ctype */
542  setlocale(LC_CTYPE, locale_monetary);
543 #endif
544 
545  /* Get formatting information for monetary */
546  setlocale(LC_MONETARY, locale_monetary);
547  extlconv = localeconv();
548 
549  /* Must copy data now in case setlocale() overwrites it */
550  worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
551  worklconv.currency_symbol = strdup(extlconv->currency_symbol);
552  worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
553  worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
554  worklconv.mon_grouping = strdup(extlconv->mon_grouping);
555  worklconv.positive_sign = strdup(extlconv->positive_sign);
556  worklconv.negative_sign = strdup(extlconv->negative_sign);
557  /* Copy scalar fields as well */
558  worklconv.int_frac_digits = extlconv->int_frac_digits;
559  worklconv.frac_digits = extlconv->frac_digits;
560  worklconv.p_cs_precedes = extlconv->p_cs_precedes;
561  worklconv.p_sep_by_space = extlconv->p_sep_by_space;
562  worklconv.n_cs_precedes = extlconv->n_cs_precedes;
563  worklconv.n_sep_by_space = extlconv->n_sep_by_space;
564  worklconv.p_sign_posn = extlconv->p_sign_posn;
565  worklconv.n_sign_posn = extlconv->n_sign_posn;
566 
567  /*
568  * Restore the prevailing locale settings; failure to do so is fatal.
569  * Possibly we could limp along with nondefault LC_MONETARY or LC_NUMERIC,
570  * but proceeding with the wrong value of LC_CTYPE would certainly be bad
571  * news; and considering that the prevailing LC_MONETARY and LC_NUMERIC
572  * are almost certainly "C", there's really no reason that restoring those
573  * should fail.
574  */
575 #ifdef WIN32
576  if (!setlocale(LC_CTYPE, save_lc_ctype))
577  elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype);
578 #endif
579  if (!setlocale(LC_MONETARY, save_lc_monetary))
580  elog(FATAL, "failed to restore LC_MONETARY to \"%s\"", save_lc_monetary);
581  if (!setlocale(LC_NUMERIC, save_lc_numeric))
582  elog(FATAL, "failed to restore LC_NUMERIC to \"%s\"", save_lc_numeric);
583 
584  /*
585  * At this point we've done our best to clean up, and can call functions
586  * that might possibly throw errors with a clean conscience. But let's
587  * make sure we don't leak any already-strdup'd fields in worklconv.
588  */
589  PG_TRY();
590  {
591  int encoding;
592 
593  /* Release the pstrdup'd locale names */
594  pfree(save_lc_monetary);
595  pfree(save_lc_numeric);
596 #ifdef WIN32
597  pfree(save_lc_ctype);
598 #endif
599 
600  /* If any of the preceding strdup calls failed, complain now. */
601  if (!struct_lconv_is_valid(&worklconv))
602  ereport(ERROR,
603  (errcode(ERRCODE_OUT_OF_MEMORY),
604  errmsg("out of memory")));
605 
606  /*
607  * Now we must perform encoding conversion from whatever's associated
608  * with the locales into the database encoding. If we can't identify
609  * the encoding implied by LC_NUMERIC or LC_MONETARY (ie we get -1),
610  * use PG_SQL_ASCII, which will result in just validating that the
611  * strings are OK in the database encoding.
612  */
614  if (encoding < 0)
616 
617  db_encoding_convert(encoding, &worklconv.decimal_point);
618  db_encoding_convert(encoding, &worklconv.thousands_sep);
619  /* grouping is not text and does not require conversion */
620 
622  if (encoding < 0)
624 
625  db_encoding_convert(encoding, &worklconv.int_curr_symbol);
626  db_encoding_convert(encoding, &worklconv.currency_symbol);
627  db_encoding_convert(encoding, &worklconv.mon_decimal_point);
628  db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
629  /* mon_grouping is not text and does not require conversion */
630  db_encoding_convert(encoding, &worklconv.positive_sign);
631  db_encoding_convert(encoding, &worklconv.negative_sign);
632  }
633  PG_CATCH();
634  {
635  free_struct_lconv(&worklconv);
636  PG_RE_THROW();
637  }
638  PG_END_TRY();
639 
640  /*
641  * Everything is good, so save the results.
642  */
643  CurrentLocaleConv = worklconv;
644  CurrentLocaleConvAllocated = true;
645  CurrentLocaleConvValid = true;
646  return &CurrentLocaleConv;
647 }
#define PG_RE_THROW()
Definition: elog.h:340
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define PG_CATCH()
Definition: elog.h:309
char * locale_numeric
Definition: pg_locale.c:87
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:425
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:375
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:394
char * locale_monetary
Definition: pg_locale.c:86

References CurrentLocaleConvValid, db_encoding_convert(), elog(), encoding, ereport, errcode(), errmsg(), ERROR, FATAL, free_struct_lconv(), locale_monetary, locale_numeric, pfree(), PG_CATCH, PG_END_TRY, pg_get_encoding_from_locale(), PG_RE_THROW, PG_SQL_ASCII, PG_TRY, pstrdup(), setlocale, and struct_lconv_is_valid().

Referenced by cash_in(), cash_numeric(), cash_out(), int4_cash(), int8_cash(), NUM_prepare_locale(), and numeric_cash().

◆ wchar2char()

size_t wchar2char ( char *  to,
const wchar_t *  from,
size_t  tolen,
pg_locale_t  locale 
)

Definition at line 2017 of file pg_locale.c.

2018 {
2019  size_t result;
2020 
2021  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2022 
2023  if (tolen == 0)
2024  return 0;
2025 
2026 #ifdef WIN32
2027 
2028  /*
2029  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
2030  * for some reason mbstowcs and wcstombs won't do this for us, so we use
2031  * MultiByteToWideChar().
2032  */
2033  if (GetDatabaseEncoding() == PG_UTF8)
2034  {
2035  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
2036  NULL, NULL);
2037  /* A zero return is failure */
2038  if (result <= 0)
2039  result = -1;
2040  else
2041  {
2042  Assert(result <= tolen);
2043  /* Microsoft counts the zero terminator in the result */
2044  result--;
2045  }
2046  }
2047  else
2048 #endif /* WIN32 */
2049  if (locale == (pg_locale_t) 0)
2050  {
2051  /* Use wcstombs directly for the default locale */
2052  result = wcstombs(to, from, tolen);
2053  }
2054  else
2055  {
2056 #ifdef HAVE_LOCALE_T
2057 #ifdef HAVE_WCSTOMBS_L
2058  /* Use wcstombs_l for nondefault locales */
2059  result = wcstombs_l(to, from, tolen, locale->info.lt);
2060 #else /* !HAVE_WCSTOMBS_L */
2061  /* We have to temporarily set the locale as current ... ugh */
2062  locale_t save_locale = uselocale(locale->info.lt);
2063 
2064  result = wcstombs(to, from, tolen);
2065 
2066  uselocale(save_locale);
2067 #endif /* HAVE_WCSTOMBS_L */
2068 #else /* !HAVE_LOCALE_T */
2069  /* Can't have locale != 0 without HAVE_LOCALE_T */
2070  elog(ERROR, "wcstombs_l is not available");
2071  result = 0; /* keep compiler quiet */
2072 #endif /* HAVE_LOCALE_T */
2073  }
2074 
2075  return result;
2076 }
#define wcstombs_l
Definition: win32_port.h:427

References Assert(), elog(), ERROR, GetDatabaseEncoding(), locale, locale_t, PG_UTF8, and wcstombs_l.

Referenced by lowerstr_with_len(), str_initcap(), str_tolower(), and str_toupper().

Variable Documentation

◆ default_locale

PGDLLIMPORT struct pg_locale_struct default_locale
extern

Definition at line 1379 of file pg_locale.c.

Referenced by CheckMyDatabase(), lc_collate_is_c(), and pg_newlocale_from_collation().

◆ locale_messages

PGDLLIMPORT char* locale_messages
extern

Definition at line 85 of file pg_locale.c.

◆ locale_monetary

PGDLLIMPORT char* locale_monetary
extern

Definition at line 86 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

PGDLLIMPORT char* locale_numeric
extern

Definition at line 87 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

PGDLLIMPORT char* locale_time
extern

Definition at line 88 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

PGDLLIMPORT char* localized_abbrev_days[]
extern

Definition at line 97 of file pg_locale.c.

Referenced by cache_locale_time(), DCH_from_char(), and DCH_to_char().

◆ localized_abbrev_months

PGDLLIMPORT char* localized_abbrev_months[]
extern

Definition at line 99 of file pg_locale.c.

Referenced by cache_locale_time(), DCH_from_char(), and DCH_to_char().

◆ localized_full_days

PGDLLIMPORT char* localized_full_days[]
extern

Definition at line 98 of file pg_locale.c.

Referenced by cache_locale_time(), DCH_from_char(), and DCH_to_char().

◆ localized_full_months

PGDLLIMPORT char* localized_full_months[]
extern

Definition at line 100 of file pg_locale.c.

Referenced by cache_locale_time(), DCH_from_char(), and DCH_to_char().