PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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
 

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)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
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

char * locale_messages
 
char * locale_monetary
 
char * locale_numeric
 
char * locale_time
 
char * localized_abbrev_days []
 
char * localized_full_days []
 
char * localized_abbrev_months []
 
char * localized_full_months []
 

Typedef Documentation

Definition at line 101 of file pg_locale.h.

Function Documentation

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

Definition at line 376 of file pg_locale.c.

References pg_perm_setlocale().

377 {
378  /*
379  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
380  * We ignore failure, as per comment above.
381  */
382 #ifdef LC_MESSAGES
383  (void) pg_perm_setlocale(LC_MESSAGES, newval);
384 #endif
385 }
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:151
#define newval
void assign_locale_monetary ( const char *  newval,
void *  extra 
)

Definition at line 313 of file pg_locale.c.

References CurrentLocaleConvValid.

314 {
315  CurrentLocaleConvValid = false;
316 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:100
void assign_locale_numeric ( const char *  newval,
void *  extra 
)

Definition at line 325 of file pg_locale.c.

References CurrentLocaleConvValid.

326 {
327  CurrentLocaleConvValid = false;
328 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:100
void assign_locale_time ( const char *  newval,
void *  extra 
)

Definition at line 337 of file pg_locale.c.

References CurrentLCTimeValid.

338 {
339  CurrentLCTimeValid = false;
340 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:101
void cache_locale_time ( void  )

Definition at line 786 of file pg_locale.c.

References cache_single_time(), CurrentLCTimeValid, DEBUG3, elog, i, locale_time, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, pfree(), pstrdup(), timenow(), and WARNING.

Referenced by DCH_to_char().

787 {
788  char *save_lc_time;
789  time_t timenow;
790  struct tm *timeinfo;
791  int i;
792 
793 #ifdef WIN32
794  char *save_lc_ctype;
795 #endif
796 
797  /* did we do this already? */
798  if (CurrentLCTimeValid)
799  return;
800 
801  elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
802 
803  /* save user's value of time locale */
804  save_lc_time = setlocale(LC_TIME, NULL);
805  if (save_lc_time)
806  save_lc_time = pstrdup(save_lc_time);
807 
808 #ifdef WIN32
809 
810  /*
811  * On WIN32, there is no way to get locale-specific time values in a
812  * specified locale, like we do for monetary/numeric. We can only get
813  * CP_ACP (see strftime_win32) or UTF16. Therefore, we get UTF16 and
814  * convert it to the database locale. However, wcsftime() internally uses
815  * LC_CTYPE, so we set it here. See the WIN32 comment near the top of
816  * PGLC_localeconv().
817  */
818 
819  /* save user's value of ctype locale */
820  save_lc_ctype = setlocale(LC_CTYPE, NULL);
821  if (save_lc_ctype)
822  save_lc_ctype = pstrdup(save_lc_ctype);
823 
824  /* use lc_time to set the ctype */
825  setlocale(LC_CTYPE, locale_time);
826 #endif
827 
828  setlocale(LC_TIME, locale_time);
829 
830  timenow = time(NULL);
831  timeinfo = localtime(&timenow);
832 
833  /* localized days */
834  for (i = 0; i < 7; i++)
835  {
836  timeinfo->tm_wday = i;
837  cache_single_time(&localized_abbrev_days[i], "%a", timeinfo);
838  cache_single_time(&localized_full_days[i], "%A", timeinfo);
839  }
840 
841  /* localized months */
842  for (i = 0; i < 12; i++)
843  {
844  timeinfo->tm_mon = i;
845  timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
846  cache_single_time(&localized_abbrev_months[i], "%b", timeinfo);
847  cache_single_time(&localized_full_months[i], "%B", timeinfo);
848  }
849 
850  /* try to restore internal settings */
851  if (save_lc_time)
852  {
853  if (!setlocale(LC_TIME, save_lc_time))
854  elog(WARNING, "failed to restore old locale");
855  pfree(save_lc_time);
856  }
857 
858 #ifdef WIN32
859  /* try to restore internal ctype settings */
860  if (save_lc_ctype)
861  {
862  if (!setlocale(LC_CTYPE, save_lc_ctype))
863  elog(WARNING, "failed to restore old locale");
864  pfree(save_lc_ctype);
865  }
866 #endif
867 
868  CurrentLCTimeValid = true;
869 }
#define DEBUG3
Definition: elog.h:23
char * pstrdup(const char *in)
Definition: mcxt.c:1076
Datum timenow(PG_FUNCTION_ARGS)
Definition: nabstime.c:997
char * localized_abbrev_months[12]
Definition: pg_locale.c:96
static struct pg_tm tm
Definition: localtime.c:107
void pfree(void *pointer)
Definition: mcxt.c:949
#define WARNING
Definition: elog.h:40
char * localized_full_days[7]
Definition: pg_locale.c:95
int i
#define elog
Definition: elog.h:219
char * localized_full_months[12]
Definition: pg_locale.c:97
char * localized_abbrev_days[7]
Definition: pg_locale.c:94
static void cache_single_time(char **dst, const char *format, const struct tm *tm)
Definition: pg_locale.c:759
char * locale_time
Definition: pg_locale.c:91
static bool CurrentLCTimeValid
Definition: pg_locale.c:101
size_t char2wchar ( wchar_t *  to,
size_t  tolen,
const char *  from,
size_t  fromlen,
pg_locale_t  locale 
)

Definition at line 1677 of file pg_locale.c.

References Assert, COLLPROVIDER_LIBC, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, locale_t, mbstowcs_l, pfree(), PG_UTF8, pg_verifymbstr(), pnstrdup(), and pg_locale_struct::provider.

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

1679 {
1680  size_t result;
1681 
1682  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1683 
1684  if (tolen == 0)
1685  return 0;
1686 
1687 #ifdef WIN32
1688  /* See WIN32 "Unicode" comment above */
1689  if (GetDatabaseEncoding() == PG_UTF8)
1690  {
1691  /* Win32 API does not work for zero-length input */
1692  if (fromlen == 0)
1693  result = 0;
1694  else
1695  {
1696  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
1697  /* A zero return is failure */
1698  if (result == 0)
1699  result = -1;
1700  }
1701 
1702  if (result != -1)
1703  {
1704  Assert(result < tolen);
1705  /* Append trailing null wchar (MultiByteToWideChar() does not) */
1706  to[result] = 0;
1707  }
1708  }
1709  else
1710 #endif /* WIN32 */
1711  {
1712  /* mbstowcs requires ending '\0' */
1713  char *str = pnstrdup(from, fromlen);
1714 
1715  if (locale == (pg_locale_t) 0)
1716  {
1717  /* Use mbstowcs directly for the default locale */
1718  result = mbstowcs(to, str, tolen);
1719  }
1720  else
1721  {
1722 #ifdef HAVE_LOCALE_T
1723 #ifdef HAVE_MBSTOWCS_L
1724  /* Use mbstowcs_l for nondefault locales */
1725  result = mbstowcs_l(to, str, tolen, locale->info.lt);
1726 #else /* !HAVE_MBSTOWCS_L */
1727  /* We have to temporarily set the locale as current ... ugh */
1728  locale_t save_locale = uselocale(locale->info.lt);
1729 
1730  result = mbstowcs(to, str, tolen);
1731 
1732  uselocale(save_locale);
1733 #endif /* HAVE_MBSTOWCS_L */
1734 #else /* !HAVE_LOCALE_T */
1735  /* Can't have locale != 0 without HAVE_LOCALE_T */
1736  elog(ERROR, "mbstowcs_l is not available");
1737  result = 0; /* keep compiler quiet */
1738 #endif /* HAVE_LOCALE_T */
1739  }
1740 
1741  pfree(str);
1742  }
1743 
1744  if (result == -1)
1745  {
1746  /*
1747  * Invalid multibyte character encountered. We try to give a useful
1748  * error message by letting pg_verifymbstr check the string. But it's
1749  * possible that the string is OK to us, and not OK to mbstowcs ---
1750  * this suggests that the LC_CTYPE locale is different from the
1751  * database encoding. Give a generic error message if verifymbstr
1752  * can't find anything wrong.
1753  */
1754  pg_verifymbstr(from, fromlen, false); /* might not return */
1755  /* but if it does ... */
1756  ereport(ERROR,
1757  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1758  errmsg("invalid multibyte character for locale"),
1759  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
1760  }
1761 
1762  return result;
1763 }
int errhint(const char *fmt,...)
Definition: elog.c:987
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1087
#define locale_t
Definition: win32.h:323
union pg_locale_struct::@120 info
int errcode(int sqlerrcode)
Definition: elog.c:575
#define mbstowcs_l
Definition: win32.h:350
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int GetDatabaseEncoding(void)
Definition: mbutils.c:1004
#define Assert(condition)
Definition: c.h:681
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define elog
Definition: elog.h:219
#define COLLPROVIDER_LIBC
Definition: pg_collation.h:86
bool check_locale ( int  category,
const char *  locale,
char **  canonname 
)

Definition at line 264 of file pg_locale.c.

References elog, pfree(), pstrdup(), and WARNING.

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

265 {
266  char *save;
267  char *res;
268 
269  if (canonname)
270  *canonname = NULL; /* in case of failure */
271 
272  save = setlocale(category, NULL);
273  if (!save)
274  return false; /* won't happen, we hope */
275 
276  /* save may be pointing at a modifiable scratch variable, see above. */
277  save = pstrdup(save);
278 
279  /* set the locale with setlocale, to see if it accepts it. */
280  res = setlocale(category, locale);
281 
282  /* save canonical name if requested. */
283  if (res && canonname)
284  *canonname = pstrdup(res);
285 
286  /* restore old value. */
287  if (!setlocale(category, save))
288  elog(WARNING, "failed to restore old locale \"%s\"", save);
289  pfree(save);
290 
291  return (res != NULL);
292 }
char * pstrdup(const char *in)
Definition: mcxt.c:1076
void pfree(void *pointer)
Definition: mcxt.c:949
#define WARNING
Definition: elog.h:40
static char * locale
Definition: initdb.c:124
#define elog
Definition: elog.h:219
bool check_locale_messages ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 353 of file pg_locale.c.

References check_locale(), and PGC_S_DEFAULT.

354 {
355  if (**newval == '\0')
356  {
357  if (source == PGC_S_DEFAULT)
358  return true;
359  else
360  return false;
361  }
362 
363  /*
364  * LC_MESSAGES category does not exist everywhere, but accept it anyway
365  *
366  * On Windows, we can't even check the value, so accept blindly
367  */
368 #if defined(LC_MESSAGES) && !defined(WIN32)
369  return check_locale(LC_MESSAGES, *newval, NULL);
370 #else
371  return true;
372 #endif
373 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define newval
bool check_locale_monetary ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 307 of file pg_locale.c.

References check_locale().

308 {
309  return check_locale(LC_MONETARY, *newval, NULL);
310 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define newval
bool check_locale_numeric ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 319 of file pg_locale.c.

References check_locale().

320 {
321  return check_locale(LC_NUMERIC, *newval, NULL);
322 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define newval
bool check_locale_time ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 331 of file pg_locale.c.

References check_locale().

332 {
333  return check_locale(LC_TIME, *newval, NULL);
334 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define newval
void check_strxfrm_bug ( void  )

Definition at line 993 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

994 {
995  char buf[32];
996  const int canary = 0x7F;
997  bool ok = true;
998 
999  /*
1000  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1001  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1002  * below that range.
1003  *
1004  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1005  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1006  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1007  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1008  */
1009  buf[7] = canary;
1010  (void) strxfrm(buf, "ab", 7);
1011  if (buf[7] != canary)
1012  ok = false;
1013 
1014  /*
1015  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1016  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1017  * affected systems ignore the length limit and modify a number of bytes
1018  * one less than the return value. The problem inputs for this bug do not
1019  * overlap those for the Solaris bug, hence a distinct test.
1020  *
1021  * Affected systems include smartos-20110926T021612Z. Affected locales
1022  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1023  */
1024  buf[1] = canary;
1025  (void) strxfrm(buf, "a", 1);
1026  if (buf[1] != canary)
1027  ok = false;
1028 
1029  if (!ok)
1030  ereport(ERROR,
1031  (errcode(ERRCODE_SYSTEM_ERROR),
1032  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1033  setlocale(LC_COLLATE, NULL)),
1034  errhint("Apply system library package updates.")));
1035 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
char* get_collation_actual_version ( char  collprovider,
const char *  collcollate 
)

Definition at line 1452 of file pg_locale.c.

References buf, COLLPROVIDER_ICU, ereport, errmsg(), ERROR, pstrdup(), and status().

Referenced by AlterCollation(), DefineCollation(), pg_collation_actual_version(), pg_import_system_collations(), and pg_newlocale_from_collation().

1453 {
1454  char *collversion;
1455 
1456 #ifdef USE_ICU
1457  if (collprovider == COLLPROVIDER_ICU)
1458  {
1459  UCollator *collator;
1460  UErrorCode status;
1461  UVersionInfo versioninfo;
1462  char buf[U_MAX_VERSION_STRING_LENGTH];
1463 
1464  status = U_ZERO_ERROR;
1465  collator = ucol_open(collcollate, &status);
1466  if (U_FAILURE(status))
1467  ereport(ERROR,
1468  (errmsg("could not open collator for locale \"%s\": %s",
1469  collcollate, u_errorName(status))));
1470  ucol_getVersion(collator, versioninfo);
1471  ucol_close(collator);
1472 
1473  u_versionToString(versioninfo, buf);
1474  collversion = pstrdup(buf);
1475  }
1476  else
1477 #endif
1478  collversion = NULL;
1479 
1480  return collversion;
1481 }
#define COLLPROVIDER_ICU
Definition: pg_collation.h:85
char * pstrdup(const char *in)
Definition: mcxt.c:1076
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
bool lc_collate_is_c ( Oid  collation)

Definition at line 1128 of file pg_locale.c.

References C_COLLATION_OID, DEFAULT_COLLATION_OID, elog, ERROR, lookup_collation_cache(), OidIsValid, and POSIX_COLLATION_OID.

Referenced by convert_string_datum(), DefineCollation(), make_greater_string(), match_special_index_operator(), spg_text_inner_consistent(), varstr_cmp(), and varstr_sortsupport().

1129 {
1130  /*
1131  * If we're asked about "collation 0", return false, so that the code will
1132  * go into the non-C path and report that the collation is bogus.
1133  */
1134  if (!OidIsValid(collation))
1135  return false;
1136 
1137  /*
1138  * If we're asked about the default collation, we have to inquire of the C
1139  * library. Cache the result so we only have to compute it once.
1140  */
1141  if (collation == DEFAULT_COLLATION_OID)
1142  {
1143  static int result = -1;
1144  char *localeptr;
1145 
1146  if (result >= 0)
1147  return (bool) result;
1148  localeptr = setlocale(LC_COLLATE, NULL);
1149  if (!localeptr)
1150  elog(ERROR, "invalid LC_COLLATE setting");
1151 
1152  if (strcmp(localeptr, "C") == 0)
1153  result = true;
1154  else if (strcmp(localeptr, "POSIX") == 0)
1155  result = true;
1156  else
1157  result = false;
1158  return (bool) result;
1159  }
1160 
1161  /*
1162  * If we're asked about the built-in C/POSIX collations, we know that.
1163  */
1164  if (collation == C_COLLATION_OID ||
1165  collation == POSIX_COLLATION_OID)
1166  return true;
1167 
1168  /*
1169  * Otherwise, we have to consult pg_collation, but we cache that.
1170  */
1171  return (lookup_collation_cache(collation, true))->collate_is_c;
1172 }
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define C_COLLATION_OID
Definition: pg_collation.h:78
#define POSIX_COLLATION_OID
Definition: pg_collation.h:81
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
bool lc_ctype_is_c ( Oid  collation)

Definition at line 1178 of file pg_locale.c.

References C_COLLATION_OID, DEFAULT_COLLATION_OID, elog, ERROR, lookup_collation_cache(), OidIsValid, and POSIX_COLLATION_OID.

Referenced by DefineCollation(), Generic_Text_IC_like(), 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().

1179 {
1180  /*
1181  * If we're asked about "collation 0", return false, so that the code will
1182  * go into the non-C path and report that the collation is bogus.
1183  */
1184  if (!OidIsValid(collation))
1185  return false;
1186 
1187  /*
1188  * If we're asked about the default collation, we have to inquire of the C
1189  * library. Cache the result so we only have to compute it once.
1190  */
1191  if (collation == DEFAULT_COLLATION_OID)
1192  {
1193  static int result = -1;
1194  char *localeptr;
1195 
1196  if (result >= 0)
1197  return (bool) result;
1198  localeptr = setlocale(LC_CTYPE, NULL);
1199  if (!localeptr)
1200  elog(ERROR, "invalid LC_CTYPE setting");
1201 
1202  if (strcmp(localeptr, "C") == 0)
1203  result = true;
1204  else if (strcmp(localeptr, "POSIX") == 0)
1205  result = true;
1206  else
1207  result = false;
1208  return (bool) result;
1209  }
1210 
1211  /*
1212  * If we're asked about the built-in C/POSIX collations, we know that.
1213  */
1214  if (collation == C_COLLATION_OID ||
1215  collation == POSIX_COLLATION_OID)
1216  return true;
1217 
1218  /*
1219  * Otherwise, we have to consult pg_collation, but we cache that.
1220  */
1221  return (lookup_collation_cache(collation, true))->ctype_is_c;
1222 }
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define C_COLLATION_OID
Definition: pg_collation.h:78
#define POSIX_COLLATION_OID
Definition: pg_collation.h:81
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1275 of file pg_locale.c.

References Anum_pg_collation_collversion, Assert, COLLOID, COLLPROVIDER_ICU, COLLPROVIDER_LIBC, DEFAULT_COLLATION_OID, 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(), MemoryContextAlloc(), MemoryContextStrdup(), NameStr, ObjectIdGetDatum, OidIsValid, pg_attribute_unused, pg_locale_struct::provider, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1(), status(), SysCacheGetAttr(), TextDatumGetCString, TopMemoryContext, and WARNING.

Referenced by DefineCollation(), Generic_Text_IC_like(), like_fixed_prefix(), pg_set_regex_collation(), str_initcap(), str_tolower(), str_toupper(), varstr_cmp(), and varstr_sortsupport().

1276 {
1277  collation_cache_entry *cache_entry;
1278 
1279  /* Callers must pass a valid OID */
1280  Assert(OidIsValid(collid));
1281 
1282  /* Return 0 for "default" collation, just in case caller forgets */
1283  if (collid == DEFAULT_COLLATION_OID)
1284  return (pg_locale_t) 0;
1285 
1286  cache_entry = lookup_collation_cache(collid, false);
1287 
1288  if (cache_entry->locale == 0)
1289  {
1290  /* We haven't computed this yet in this session, so do it */
1291  HeapTuple tp;
1292  Form_pg_collation collform;
1293  const char *collcollate;
1294  const char *collctype pg_attribute_unused();
1295  struct pg_locale_struct result;
1296  pg_locale_t resultp;
1297  Datum collversion;
1298  bool isnull;
1299 
1300  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1301  if (!HeapTupleIsValid(tp))
1302  elog(ERROR, "cache lookup failed for collation %u", collid);
1303  collform = (Form_pg_collation) GETSTRUCT(tp);
1304 
1305  collcollate = NameStr(collform->collcollate);
1306  collctype = NameStr(collform->collctype);
1307 
1308  /* We'll fill in the result struct locally before allocating memory */
1309  memset(&result, 0, sizeof(result));
1310  result.provider = collform->collprovider;
1311 
1312  if (collform->collprovider == COLLPROVIDER_LIBC)
1313  {
1314 #ifdef HAVE_LOCALE_T
1315  locale_t loc;
1316 
1317  if (strcmp(collcollate, collctype) == 0)
1318  {
1319  /* Normal case where they're the same */
1320  errno = 0;
1321 #ifndef WIN32
1322  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1323  NULL);
1324 #else
1325  loc = _create_locale(LC_ALL, collcollate);
1326 #endif
1327  if (!loc)
1328  report_newlocale_failure(collcollate);
1329  }
1330  else
1331  {
1332 #ifndef WIN32
1333  /* We need two newlocale() steps */
1334  locale_t loc1;
1335 
1336  errno = 0;
1337  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1338  if (!loc1)
1339  report_newlocale_failure(collcollate);
1340  errno = 0;
1341  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1342  if (!loc)
1343  report_newlocale_failure(collctype);
1344 #else
1345 
1346  /*
1347  * XXX The _create_locale() API doesn't appear to support
1348  * this. Could perhaps be worked around by changing
1349  * pg_locale_t to contain two separate fields.
1350  */
1351  ereport(ERROR,
1352  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1353  errmsg("collations with different collate and ctype values are not supported on this platform")));
1354 #endif
1355  }
1356 
1357  result.info.lt = loc;
1358 #else /* not HAVE_LOCALE_T */
1359  /* platform that doesn't support locale_t */
1360  ereport(ERROR,
1361  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1362  errmsg("collation provider LIBC is not supported on this platform")));
1363 #endif /* not HAVE_LOCALE_T */
1364  }
1365  else if (collform->collprovider == COLLPROVIDER_ICU)
1366  {
1367 #ifdef USE_ICU
1368  UCollator *collator;
1369  UErrorCode status;
1370 
1371  if (strcmp(collcollate, collctype) != 0)
1372  ereport(ERROR,
1373  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1374  errmsg("collations with different collate and ctype values are not supported by ICU")));
1375 
1376  status = U_ZERO_ERROR;
1377  collator = ucol_open(collcollate, &status);
1378  if (U_FAILURE(status))
1379  ereport(ERROR,
1380  (errmsg("could not open collator for locale \"%s\": %s",
1381  collcollate, u_errorName(status))));
1382 
1383  /* We will leak this string if we get an error below :-( */
1384  result.info.icu.locale = MemoryContextStrdup(TopMemoryContext,
1385  collcollate);
1386  result.info.icu.ucol = collator;
1387 #else /* not USE_ICU */
1388  /* could get here if a collation was created by a build with ICU */
1389  ereport(ERROR,
1390  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1391  errmsg("ICU is not supported in this build"), \
1392  errhint("You need to rebuild PostgreSQL using --with-icu.")));
1393 #endif /* not USE_ICU */
1394  }
1395 
1397  &isnull);
1398  if (!isnull)
1399  {
1400  char *actual_versionstr;
1401  char *collversionstr;
1402 
1403  actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
1404  if (!actual_versionstr)
1405  {
1406  /*
1407  * This could happen when specifying a version in CREATE
1408  * COLLATION for a libc locale, or manually creating a mess in
1409  * the catalogs.
1410  */
1411  ereport(ERROR,
1412  (errmsg("collation \"%s\" has no actual version, but a version was specified",
1413  NameStr(collform->collname))));
1414  }
1415  collversionstr = TextDatumGetCString(collversion);
1416 
1417  if (strcmp(actual_versionstr, collversionstr) != 0)
1418  ereport(WARNING,
1419  (errmsg("collation \"%s\" has version mismatch",
1420  NameStr(collform->collname)),
1421  errdetail("The collation in the database was created using version %s, "
1422  "but the operating system provides version %s.",
1423  collversionstr, actual_versionstr),
1424  errhint("Rebuild all objects affected by this collation and run "
1425  "ALTER COLLATION %s REFRESH VERSION, "
1426  "or build PostgreSQL with the right library version.",
1427  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1428  NameStr(collform->collname)))));
1429  }
1430 
1431  ReleaseSysCache(tp);
1432 
1433  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1434  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1435  *resultp = result;
1436 
1437  cache_entry->locale = resultp;
1438  }
1439 
1440  return cache_entry->locale;
1441 }
#define COLLPROVIDER_ICU
Definition: pg_collation.h:85
#define Anum_pg_collation_collversion
Definition: pg_collation.h:66
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define locale_t
Definition: win32.h:323
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:532
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:43
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10476
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
pg_locale_t locale
Definition: pg_locale.c:125
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define pg_attribute_unused()
Definition: c.h:618
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
Definition: pg_locale.c:119
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define COLLPROVIDER_LIBC
Definition: pg_collation.h:86
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1452
char* pg_perm_setlocale ( int  category,
const char *  locale 
)

Definition at line 151 of file pg_locale.c.

References elog, FATAL, GetDatabaseEncoding(), lc_collate_envbuf, lc_ctype_envbuf, LC_ENV_BUFSIZE, lc_monetary_envbuf, lc_numeric_envbuf, lc_time_envbuf, putenv, SetMessageEncoding(), snprintf(), and strlcpy().

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

152 {
153  char *result;
154  const char *envvar;
155  char *envbuf;
156 
157 #ifndef WIN32
158  result = setlocale(category, locale);
159 #else
160 
161  /*
162  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
163  * the given value is good and set it in the environment variables. We
164  * must ignore attempts to set to "", which means "keep using the old
165  * environment value".
166  */
167 #ifdef LC_MESSAGES
168  if (category == LC_MESSAGES)
169  {
170  result = (char *) locale;
171  if (locale == NULL || locale[0] == '\0')
172  return result;
173  }
174  else
175 #endif
176  result = setlocale(category, locale);
177 #endif /* WIN32 */
178 
179  if (result == NULL)
180  return result; /* fall out immediately on failure */
181 
182  /*
183  * Use the right encoding in translated messages. Under ENABLE_NLS, let
184  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
185  * format strings are ASCII, but database-encoding strings may enter the
186  * message via %s. This makes the overall message encoding equal to the
187  * database encoding.
188  */
189  if (category == LC_CTYPE)
190  {
191  static char save_lc_ctype[LC_ENV_BUFSIZE];
192 
193  /* copy setlocale() return value before callee invokes it again */
194  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
195  result = save_lc_ctype;
196 
197 #ifdef ENABLE_NLS
198  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
199 #else
201 #endif
202  }
203 
204  switch (category)
205  {
206  case LC_COLLATE:
207  envvar = "LC_COLLATE";
208  envbuf = lc_collate_envbuf;
209  break;
210  case LC_CTYPE:
211  envvar = "LC_CTYPE";
212  envbuf = lc_ctype_envbuf;
213  break;
214 #ifdef LC_MESSAGES
215  case LC_MESSAGES:
216  envvar = "LC_MESSAGES";
217  envbuf = lc_messages_envbuf;
218 #ifdef WIN32
219  result = IsoLocaleName(locale);
220  if (result == NULL)
221  result = (char *) locale;
222 #endif /* WIN32 */
223  break;
224 #endif /* LC_MESSAGES */
225  case LC_MONETARY:
226  envvar = "LC_MONETARY";
227  envbuf = lc_monetary_envbuf;
228  break;
229  case LC_NUMERIC:
230  envvar = "LC_NUMERIC";
231  envbuf = lc_numeric_envbuf;
232  break;
233  case LC_TIME:
234  envvar = "LC_TIME";
235  envbuf = lc_time_envbuf;
236  break;
237  default:
238  elog(FATAL, "unrecognized LC category: %d", category);
239  envvar = NULL; /* keep compiler quiet */
240  envbuf = NULL;
241  return NULL;
242  }
243 
244  snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
245 
246  if (putenv(envbuf))
247  return NULL;
248 
249  return result;
250 }
static char lc_numeric_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:114
void SetMessageEncoding(int encoding)
Definition: mbutils.c:908
static char lc_monetary_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:113
#define LC_ENV_BUFSIZE
Definition: pg_locale.c:105
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define putenv(x)
Definition: win32.h:411
static char lc_time_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:115
#define FATAL
Definition: elog.h:52
static char lc_ctype_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:108
int GetDatabaseEncoding(void)
Definition: mbutils.c:1004
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static char * locale
Definition: initdb.c:124
#define elog
Definition: elog.h:219
static char lc_collate_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:107
struct lconv* PGLC_localeconv ( void  )

Definition at line 483 of file pg_locale.c.

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

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

484 {
485  static struct lconv CurrentLocaleConv;
486  static bool CurrentLocaleConvAllocated = false;
487  struct lconv *extlconv;
488  struct lconv worklconv;
489  bool trouble = false;
490  char *save_lc_monetary;
491  char *save_lc_numeric;
492 #ifdef WIN32
493  char *save_lc_ctype;
494 #endif
495 
496  /* Did we do it already? */
498  return &CurrentLocaleConv;
499 
500  /* Free any already-allocated storage */
501  if (CurrentLocaleConvAllocated)
502  {
503  free_struct_lconv(&CurrentLocaleConv);
504  CurrentLocaleConvAllocated = false;
505  }
506 
507  /*
508  * This is tricky because we really don't want to risk throwing error
509  * while the locale is set to other than our usual settings. Therefore,
510  * the process is: collect the usual settings, set locale to special
511  * setting, copy relevant data into worklconv using strdup(), restore
512  * normal settings, convert data to desired encoding, and finally stash
513  * the collected data in CurrentLocaleConv. This makes it safe if we
514  * throw an error during encoding conversion or run out of memory anywhere
515  * in the process. All data pointed to by struct lconv members is
516  * allocated with strdup, to avoid premature elog(ERROR) and to allow
517  * using a single cleanup routine.
518  */
519  memset(&worklconv, 0, sizeof(worklconv));
520 
521  /* Save user's values of monetary and numeric locales */
522  save_lc_monetary = setlocale(LC_MONETARY, NULL);
523  if (save_lc_monetary)
524  save_lc_monetary = pstrdup(save_lc_monetary);
525 
526  save_lc_numeric = setlocale(LC_NUMERIC, NULL);
527  if (save_lc_numeric)
528  save_lc_numeric = pstrdup(save_lc_numeric);
529 
530 #ifdef WIN32
531 
532  /*
533  * Ideally, monetary and numeric local symbols could be returned in any
534  * server encoding. Unfortunately, the WIN32 API does not allow
535  * setlocale() to return values in a codepage/CTYPE that uses more than
536  * two bytes per character, such as UTF-8:
537  *
538  * http://msdn.microsoft.com/en-us/library/x99tb11d.aspx
539  *
540  * Evidently, LC_CTYPE allows us to control the encoding used for strings
541  * returned by localeconv(). The Open Group standard, mentioned at the
542  * top of this C file, doesn't explicitly state this.
543  *
544  * Therefore, we set LC_CTYPE to match LC_NUMERIC or LC_MONETARY (which
545  * cannot be UTF8), call localeconv(), and then convert from the
546  * numeric/monetary LC_CTYPE to the server encoding. One example use of
547  * this is for the Euro symbol.
548  *
549  * Perhaps someday we will use GetLocaleInfoW() which returns values in
550  * UTF16 and convert from that.
551  */
552 
553  /* save user's value of ctype locale */
554  save_lc_ctype = setlocale(LC_CTYPE, NULL);
555  if (save_lc_ctype)
556  save_lc_ctype = pstrdup(save_lc_ctype);
557 
558  /* Here begins the critical section where we must not throw error */
559 
560  /* use numeric to set the ctype */
561  setlocale(LC_CTYPE, locale_numeric);
562 #endif
563 
564  /* Get formatting information for numeric */
565  setlocale(LC_NUMERIC, locale_numeric);
566  extlconv = localeconv();
567 
568  /* Must copy data now in case setlocale() overwrites it */
569  worklconv.decimal_point = strdup(extlconv->decimal_point);
570  worklconv.thousands_sep = strdup(extlconv->thousands_sep);
571  worklconv.grouping = strdup(extlconv->grouping);
572 
573 #ifdef WIN32
574  /* use monetary to set the ctype */
575  setlocale(LC_CTYPE, locale_monetary);
576 #endif
577 
578  /* Get formatting information for monetary */
579  setlocale(LC_MONETARY, locale_monetary);
580  extlconv = localeconv();
581 
582  /* Must copy data now in case setlocale() overwrites it */
583  worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
584  worklconv.currency_symbol = strdup(extlconv->currency_symbol);
585  worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
586  worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
587  worklconv.mon_grouping = strdup(extlconv->mon_grouping);
588  worklconv.positive_sign = strdup(extlconv->positive_sign);
589  worklconv.negative_sign = strdup(extlconv->negative_sign);
590  /* Copy scalar fields as well */
591  worklconv.int_frac_digits = extlconv->int_frac_digits;
592  worklconv.frac_digits = extlconv->frac_digits;
593  worklconv.p_cs_precedes = extlconv->p_cs_precedes;
594  worklconv.p_sep_by_space = extlconv->p_sep_by_space;
595  worklconv.n_cs_precedes = extlconv->n_cs_precedes;
596  worklconv.n_sep_by_space = extlconv->n_sep_by_space;
597  worklconv.p_sign_posn = extlconv->p_sign_posn;
598  worklconv.n_sign_posn = extlconv->n_sign_posn;
599 
600  /* Try to restore internal settings */
601  if (save_lc_monetary)
602  {
603  if (!setlocale(LC_MONETARY, save_lc_monetary))
604  trouble = true;
605  }
606 
607  if (save_lc_numeric)
608  {
609  if (!setlocale(LC_NUMERIC, save_lc_numeric))
610  trouble = true;
611  }
612 
613 #ifdef WIN32
614  /* Try to restore internal ctype settings */
615  if (save_lc_ctype)
616  {
617  if (!setlocale(LC_CTYPE, save_lc_ctype))
618  trouble = true;
619  }
620 #endif
621 
622  /*
623  * At this point we've done our best to clean up, and can call functions
624  * that might possibly throw errors with a clean conscience. But let's
625  * make sure we don't leak any already-strdup'd fields in worklconv.
626  */
627  PG_TRY();
628  {
629  int encoding;
630 
631  /*
632  * Report it if we failed to restore anything. Perhaps this should be
633  * FATAL, rather than continuing with bad locale settings?
634  */
635  if (trouble)
636  elog(WARNING, "failed to restore old locale");
637 
638  /* Release the pstrdup'd locale names */
639  if (save_lc_monetary)
640  pfree(save_lc_monetary);
641  if (save_lc_numeric)
642  pfree(save_lc_numeric);
643 #ifdef WIN32
644  if (save_lc_ctype)
645  pfree(save_lc_ctype);
646 #endif
647 
648  /* If any of the preceding strdup calls failed, complain now. */
649  if (!struct_lconv_is_valid(&worklconv))
650  ereport(ERROR,
651  (errcode(ERRCODE_OUT_OF_MEMORY),
652  errmsg("out of memory")));
653 
654  /*
655  * Now we must perform encoding conversion from whatever's associated
656  * with the locale into the database encoding.
657  */
659 
660  db_encoding_convert(encoding, &worklconv.decimal_point);
661  db_encoding_convert(encoding, &worklconv.thousands_sep);
662  /* grouping is not text and does not require conversion */
663 
665 
666  db_encoding_convert(encoding, &worklconv.int_curr_symbol);
667  db_encoding_convert(encoding, &worklconv.currency_symbol);
668  db_encoding_convert(encoding, &worklconv.mon_decimal_point);
669  db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
670  /* mon_grouping is not text and does not require conversion */
671  db_encoding_convert(encoding, &worklconv.positive_sign);
672  db_encoding_convert(encoding, &worklconv.negative_sign);
673  }
674  PG_CATCH();
675  {
676  free_struct_lconv(&worklconv);
677  PG_RE_THROW();
678  }
679  PG_END_TRY();
680 
681  /*
682  * Everything is good, so save the results.
683  */
684  CurrentLocaleConv = worklconv;
685  CurrentLocaleConvAllocated = true;
686  CurrentLocaleConvValid = true;
687  return &CurrentLocaleConv;
688 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:100
char * pstrdup(const char *in)
Definition: mcxt.c:1076
int errcode(int sqlerrcode)
Definition: elog.c:575
char * locale_numeric
Definition: pg_locale.c:90
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:393
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:433
static char * encoding
Definition: initdb.c:123
#define PG_CATCH()
Definition: elog.h:293
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:422
#define PG_RE_THROW()
Definition: elog.h:314
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
char * locale_monetary
Definition: pg_locale.c:89
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:453
#define PG_END_TRY()
Definition: elog.h:300
size_t wchar2char ( char *  to,
const wchar_t *  from,
size_t  tolen,
pg_locale_t  locale 
)

Definition at line 1606 of file pg_locale.c.

References Assert, COLLPROVIDER_LIBC, elog, ERROR, GetDatabaseEncoding(), pg_locale_struct::info, locale_t, PG_UTF8, pg_locale_struct::provider, and wcstombs_l.

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

1607 {
1608  size_t result;
1609 
1610  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1611 
1612  if (tolen == 0)
1613  return 0;
1614 
1615 #ifdef WIN32
1616 
1617  /*
1618  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
1619  * for some reason mbstowcs and wcstombs won't do this for us, so we use
1620  * MultiByteToWideChar().
1621  */
1622  if (GetDatabaseEncoding() == PG_UTF8)
1623  {
1624  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
1625  NULL, NULL);
1626  /* A zero return is failure */
1627  if (result <= 0)
1628  result = -1;
1629  else
1630  {
1631  Assert(result <= tolen);
1632  /* Microsoft counts the zero terminator in the result */
1633  result--;
1634  }
1635  }
1636  else
1637 #endif /* WIN32 */
1638  if (locale == (pg_locale_t) 0)
1639  {
1640  /* Use wcstombs directly for the default locale */
1641  result = wcstombs(to, from, tolen);
1642  }
1643  else
1644  {
1645 #ifdef HAVE_LOCALE_T
1646 #ifdef HAVE_WCSTOMBS_L
1647  /* Use wcstombs_l for nondefault locales */
1648  result = wcstombs_l(to, from, tolen, locale->info.lt);
1649 #else /* !HAVE_WCSTOMBS_L */
1650  /* We have to temporarily set the locale as current ... ugh */
1651  locale_t save_locale = uselocale(locale->info.lt);
1652 
1653  result = wcstombs(to, from, tolen);
1654 
1655  uselocale(save_locale);
1656 #endif /* HAVE_WCSTOMBS_L */
1657 #else /* !HAVE_LOCALE_T */
1658  /* Can't have locale != 0 without HAVE_LOCALE_T */
1659  elog(ERROR, "wcstombs_l is not available");
1660  result = 0; /* keep compiler quiet */
1661 #endif /* HAVE_LOCALE_T */
1662  }
1663 
1664  return result;
1665 }
#define locale_t
Definition: win32.h:323
#define wcstombs_l
Definition: win32.h:349
union pg_locale_struct::@120 info
#define ERROR
Definition: elog.h:43
int GetDatabaseEncoding(void)
Definition: mbutils.c:1004
#define Assert(condition)
Definition: c.h:681
#define elog
Definition: elog.h:219
#define COLLPROVIDER_LIBC
Definition: pg_collation.h:86

Variable Documentation

char* locale_messages

Definition at line 88 of file pg_locale.c.

char* locale_monetary

Definition at line 89 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_numeric

Definition at line 90 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_time

Definition at line 91 of file pg_locale.c.

Referenced by cache_locale_time().

char* localized_abbrev_days[]

Definition at line 94 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_abbrev_months[]

Definition at line 96 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_days[]

Definition at line 95 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_months[]

Definition at line 97 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().