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
 

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

◆ pg_locale_t

typedef struct pg_locale_struct* pg_locale_t

Definition at line 102 of file pg_locale.h.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 391 of file pg_locale.c.

References pg_perm_setlocale().

392 {
393  /*
394  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
395  * We ignore failure, as per comment above.
396  */
397 #ifdef LC_MESSAGES
398  (void) pg_perm_setlocale(LC_MESSAGES, newval);
399 #endif
400 }
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:166
#define newval

◆ assign_locale_monetary()

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

Definition at line 328 of file pg_locale.c.

References CurrentLocaleConvValid.

329 {
330  CurrentLocaleConvValid = false;
331 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:112

◆ assign_locale_numeric()

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

Definition at line 340 of file pg_locale.c.

References CurrentLocaleConvValid.

341 {
342  CurrentLocaleConvValid = false;
343 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:112

◆ assign_locale_time()

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

Definition at line 352 of file pg_locale.c.

References CurrentLCTimeValid.

353 {
354  CurrentLCTimeValid = false;
355 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:113

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 780 of file pg_locale.c.

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_strcasecmp(), PG_UTF8, pstrdup(), setlocale, tm, and wchar2char().

Referenced by DCH_from_char(), and DCH_to_char().

781 {
782  char buf[(2 * 7 + 2 * 12) * MAX_L10N_DATA];
783  char *bufptr;
784  time_t timenow;
785  struct tm *timeinfo;
786  bool strftimefail = false;
787  int encoding;
788  int i;
789  char *save_lc_time;
790 #ifdef WIN32
791  char *save_lc_ctype;
792 #endif
793 
794  /* did we do this already? */
795  if (CurrentLCTimeValid)
796  return;
797 
798  elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
799 
800  /*
801  * As in PGLC_localeconv(), it's critical that we not throw error while
802  * libc's locale settings have nondefault values. Hence, we just call
803  * strftime() within the critical section, and then convert and save its
804  * results afterwards.
805  */
806 
807  /* Save prevailing value of time locale */
808  save_lc_time = setlocale(LC_TIME, NULL);
809  if (!save_lc_time)
810  elog(ERROR, "setlocale(NULL) failed");
811  save_lc_time = pstrdup(save_lc_time);
812 
813 #ifdef WIN32
814 
815  /*
816  * On Windows, it appears that wcsftime() internally uses LC_CTYPE, so we
817  * must set it here. This code looks the same as what PGLC_localeconv()
818  * does, but the underlying reason is different: this does NOT determine
819  * the encoding we'll get back from strftime_win32().
820  */
821 
822  /* Save prevailing value of ctype locale */
823  save_lc_ctype = setlocale(LC_CTYPE, NULL);
824  if (!save_lc_ctype)
825  elog(ERROR, "setlocale(NULL) failed");
826  save_lc_ctype = pstrdup(save_lc_ctype);
827 
828  /* use lc_time to set the ctype */
829  setlocale(LC_CTYPE, locale_time);
830 #endif
831 
832  setlocale(LC_TIME, locale_time);
833 
834  /* We use times close to current time as data for strftime(). */
835  timenow = time(NULL);
836  timeinfo = localtime(&timenow);
837 
838  /* Store the strftime results in MAX_L10N_DATA-sized portions of buf[] */
839  bufptr = buf;
840 
841  /*
842  * MAX_L10N_DATA is sufficient buffer space for every known locale, and
843  * POSIX defines no strftime() errors. (Buffer space exhaustion is not an
844  * error.) An implementation might report errors (e.g. ENOMEM) by
845  * returning 0 (or, less plausibly, a negative value) and setting errno.
846  * Report errno just in case the implementation did that, but clear it in
847  * advance of the calls so we don't emit a stale, unrelated errno.
848  */
849  errno = 0;
850 
851  /* localized days */
852  for (i = 0; i < 7; i++)
853  {
854  timeinfo->tm_wday = i;
855  if (strftime(bufptr, MAX_L10N_DATA, "%a", timeinfo) <= 0)
856  strftimefail = true;
857  bufptr += MAX_L10N_DATA;
858  if (strftime(bufptr, MAX_L10N_DATA, "%A", timeinfo) <= 0)
859  strftimefail = true;
860  bufptr += MAX_L10N_DATA;
861  }
862 
863  /* localized months */
864  for (i = 0; i < 12; i++)
865  {
866  timeinfo->tm_mon = i;
867  timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
868  if (strftime(bufptr, MAX_L10N_DATA, "%b", timeinfo) <= 0)
869  strftimefail = true;
870  bufptr += MAX_L10N_DATA;
871  if (strftime(bufptr, MAX_L10N_DATA, "%B", timeinfo) <= 0)
872  strftimefail = true;
873  bufptr += MAX_L10N_DATA;
874  }
875 
876  /*
877  * Restore the prevailing locale settings; as in PGLC_localeconv(),
878  * failure to do so is fatal.
879  */
880 #ifdef WIN32
881  if (!setlocale(LC_CTYPE, save_lc_ctype))
882  elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype);
883 #endif
884  if (!setlocale(LC_TIME, save_lc_time))
885  elog(FATAL, "failed to restore LC_TIME to \"%s\"", save_lc_time);
886 
887  /*
888  * At this point we've done our best to clean up, and can throw errors, or
889  * call functions that might throw errors, with a clean conscience.
890  */
891  if (strftimefail)
892  elog(ERROR, "strftime() failed: %m");
893 
894  /* Release the pstrdup'd locale names */
895  pfree(save_lc_time);
896 #ifdef WIN32
897  pfree(save_lc_ctype);
898 #endif
899 
900 #ifndef WIN32
901 
902  /*
903  * As in PGLC_localeconv(), we must convert strftime()'s output from the
904  * encoding implied by LC_TIME to the database encoding. If we can't
905  * identify the LC_TIME encoding, just perform encoding validation.
906  */
907  encoding = pg_get_encoding_from_locale(locale_time, true);
908  if (encoding < 0)
909  encoding = PG_SQL_ASCII;
910 
911 #else
912 
913  /*
914  * On Windows, strftime_win32() always returns UTF8 data, so convert from
915  * that if necessary.
916  */
917  encoding = PG_UTF8;
918 
919 #endif /* WIN32 */
920 
921  bufptr = buf;
922 
923  /* localized days */
924  for (i = 0; i < 7; i++)
925  {
926  cache_single_string(&localized_abbrev_days[i], bufptr, encoding);
927  bufptr += MAX_L10N_DATA;
928  cache_single_string(&localized_full_days[i], bufptr, encoding);
929  bufptr += MAX_L10N_DATA;
930  }
931  localized_abbrev_days[7] = NULL;
932  localized_full_days[7] = NULL;
933 
934  /* localized months */
935  for (i = 0; i < 12; i++)
936  {
937  cache_single_string(&localized_abbrev_months[i], bufptr, encoding);
938  bufptr += MAX_L10N_DATA;
939  cache_single_string(&localized_full_months[i], bufptr, encoding);
940  bufptr += MAX_L10N_DATA;
941  }
942  localized_abbrev_months[12] = NULL;
943  localized_full_months[12] = NULL;
944 
945  CurrentLCTimeValid = true;
946 }
#define setlocale(a, b)
Definition: win32_port.h:408
#define DEBUG3
Definition: elog.h:23
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static struct pg_tm tm
Definition: localtime.c:108
void pfree(void *pointer)
Definition: mcxt.c:1056
#define MAX_L10N_DATA
Definition: pg_locale.c:90
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:108
static char * buf
Definition: pg_test_fsync.c:67
char * localized_full_days[7+1]
Definition: pg_locale.c:107
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
char * localized_full_months[12+1]
Definition: pg_locale.c:109
static void cache_single_string(char **dst, const char *src, int encoding)
Definition: pg_locale.c:757
int32 encoding
Definition: pg_database.h:41
#define elog(elevel,...)
Definition: elog.h:214
int i
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:106
char * locale_time
Definition: pg_locale.c:97
static bool CurrentLCTimeValid
Definition: pg_locale.c:113

◆ char2wchar()

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

Definition at line 1891 of file pg_locale.c.

References Assert, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, locale_t, mbstowcs_l, pfree(), PG_UTF8, pg_verifymbstr(), pnstrdup(), pg_locale_struct::provider, 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().

1893 {
1894  size_t result;
1895 
1896  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1897 
1898  if (tolen == 0)
1899  return 0;
1900 
1901 #ifdef WIN32
1902  /* See WIN32 "Unicode" comment above */
1903  if (GetDatabaseEncoding() == PG_UTF8)
1904  {
1905  /* Win32 API does not work for zero-length input */
1906  if (fromlen == 0)
1907  result = 0;
1908  else
1909  {
1910  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
1911  /* A zero return is failure */
1912  if (result == 0)
1913  result = -1;
1914  }
1915 
1916  if (result != -1)
1917  {
1918  Assert(result < tolen);
1919  /* Append trailing null wchar (MultiByteToWideChar() does not) */
1920  to[result] = 0;
1921  }
1922  }
1923  else
1924 #endif /* WIN32 */
1925  {
1926  /* mbstowcs requires ending '\0' */
1927  char *str = pnstrdup(from, fromlen);
1928 
1929  if (locale == (pg_locale_t) 0)
1930  {
1931  /* Use mbstowcs directly for the default locale */
1932  result = mbstowcs(to, str, tolen);
1933  }
1934  else
1935  {
1936 #ifdef HAVE_LOCALE_T
1937 #ifdef HAVE_MBSTOWCS_L
1938  /* Use mbstowcs_l for nondefault locales */
1939  result = mbstowcs_l(to, str, tolen, locale->info.lt);
1940 #else /* !HAVE_MBSTOWCS_L */
1941  /* We have to temporarily set the locale as current ... ugh */
1942  locale_t save_locale = uselocale(locale->info.lt);
1943 
1944  result = mbstowcs(to, str, tolen);
1945 
1946  uselocale(save_locale);
1947 #endif /* HAVE_MBSTOWCS_L */
1948 #else /* !HAVE_LOCALE_T */
1949  /* Can't have locale != 0 without HAVE_LOCALE_T */
1950  elog(ERROR, "mbstowcs_l is not available");
1951  result = 0; /* keep compiler quiet */
1952 #endif /* HAVE_LOCALE_T */
1953  }
1954 
1955  pfree(str);
1956  }
1957 
1958  if (result == -1)
1959  {
1960  /*
1961  * Invalid multibyte character encountered. We try to give a useful
1962  * error message by letting pg_verifymbstr check the string. But it's
1963  * possible that the string is OK to us, and not OK to mbstowcs ---
1964  * this suggests that the LC_CTYPE locale is different from the
1965  * database encoding. Give a generic error message if pg_verifymbstr
1966  * can't find anything wrong.
1967  */
1968  pg_verifymbstr(from, fromlen, false); /* might not return */
1969  /* but if it does ... */
1970  ereport(ERROR,
1971  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1972  errmsg("invalid multibyte character for locale"),
1973  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
1974  }
1975 
1976  return result;
1977 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
int errcode(int sqlerrcode)
Definition: elog.c:610
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define locale_t
Definition: win32_port.h:363
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1446
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
#define mbstowcs_l
Definition: win32_port.h:390
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
union pg_locale_struct::@142 info

◆ check_locale()

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

Definition at line 279 of file pg_locale.c.

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

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

280 {
281  char *save;
282  char *res;
283 
284  if (canonname)
285  *canonname = NULL; /* in case of failure */
286 
287  save = setlocale(category, NULL);
288  if (!save)
289  return false; /* won't happen, we hope */
290 
291  /* save may be pointing at a modifiable scratch variable, see above. */
292  save = pstrdup(save);
293 
294  /* set the locale with setlocale, to see if it accepts it. */
295  res = setlocale(category, locale);
296 
297  /* save canonical name if requested. */
298  if (res && canonname)
299  *canonname = pstrdup(res);
300 
301  /* restore old value. */
302  if (!setlocale(category, save))
303  elog(WARNING, "failed to restore old locale \"%s\"", save);
304  pfree(save);
305 
306  return (res != NULL);
307 }
#define setlocale(a, b)
Definition: win32_port.h:408
char * pstrdup(const char *in)
Definition: mcxt.c:1186
void pfree(void *pointer)
Definition: mcxt.c:1056
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:214
static char * locale
Definition: initdb.c:125

◆ check_locale_messages()

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

Definition at line 368 of file pg_locale.c.

References check_locale(), and PGC_S_DEFAULT.

369 {
370  if (**newval == '\0')
371  {
372  if (source == PGC_S_DEFAULT)
373  return true;
374  else
375  return false;
376  }
377 
378  /*
379  * LC_MESSAGES category does not exist everywhere, but accept it anyway
380  *
381  * On Windows, we can't even check the value, so accept blindly
382  */
383 #if defined(LC_MESSAGES) && !defined(WIN32)
384  return check_locale(LC_MESSAGES, *newval, NULL);
385 #else
386  return true;
387 #endif
388 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:279
#define newval

◆ check_locale_monetary()

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

Definition at line 322 of file pg_locale.c.

References check_locale().

323 {
324  return check_locale(LC_MONETARY, *newval, NULL);
325 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:279
#define newval

◆ check_locale_numeric()

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

Definition at line 334 of file pg_locale.c.

References check_locale().

335 {
336  return check_locale(LC_NUMERIC, *newval, NULL);
337 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:279
#define newval

◆ check_locale_time()

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

Definition at line 346 of file pg_locale.c.

References check_locale().

347 {
348  return check_locale(LC_TIME, *newval, NULL);
349 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:279
#define newval

◆ check_strxfrm_bug()

void check_strxfrm_bug ( void  )

Definition at line 1051 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

1052 {
1053  char buf[32];
1054  const int canary = 0x7F;
1055  bool ok = true;
1056 
1057  /*
1058  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1059  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1060  * below that range.
1061  *
1062  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1063  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1064  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1065  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1066  */
1067  buf[7] = canary;
1068  (void) strxfrm(buf, "ab", 7);
1069  if (buf[7] != canary)
1070  ok = false;
1071 
1072  /*
1073  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1074  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1075  * affected systems ignore the length limit and modify a number of bytes
1076  * one less than the return value. The problem inputs for this bug do not
1077  * overlap those for the Solaris bug, hence a distinct test.
1078  *
1079  * Affected systems include smartos-20110926T021612Z. Affected locales
1080  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1081  */
1082  buf[1] = canary;
1083  (void) strxfrm(buf, "a", 1);
1084  if (buf[1] != canary)
1085  ok = false;
1086 
1087  if (!ok)
1088  ereport(ERROR,
1089  (errcode(ERRCODE_SYSTEM_ERROR),
1090  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1091  setlocale(LC_COLLATE, NULL)),
1092  errhint("Apply system library package updates.")));
1093 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define setlocale(a, b)
Definition: win32_port.h:408
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg_internal(const char *fmt,...)
Definition: elog.c:911

◆ get_collation_actual_version()

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

Definition at line 1510 of file pg_locale.c.

References asc_tolower(), buf, ereport, errcode(), errmsg(), ERROR, get_encoding_name_for_icu(), GetDatabaseEncoding(), name, palloc(), pfree(), pg_attribute_unused(), pg_encoding_to_char(), pg_strcasecmp(), psprintf(), pstrdup(), status(), generate_unaccent_rules::str, and value.

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

1511 {
1512  char *collversion = NULL;
1513 
1514 #ifdef USE_ICU
1515  if (collprovider == COLLPROVIDER_ICU)
1516  {
1517  UCollator *collator;
1518  UErrorCode status;
1519  UVersionInfo versioninfo;
1520  char buf[U_MAX_VERSION_STRING_LENGTH];
1521 
1522  status = U_ZERO_ERROR;
1523  collator = ucol_open(collcollate, &status);
1524  if (U_FAILURE(status))
1525  ereport(ERROR,
1526  (errmsg("could not open collator for locale \"%s\": %s",
1527  collcollate, u_errorName(status))));
1528  ucol_getVersion(collator, versioninfo);
1529  ucol_close(collator);
1530 
1531  u_versionToString(versioninfo, buf);
1532  collversion = pstrdup(buf);
1533  }
1534  else
1535 #endif
1536  if (collprovider == COLLPROVIDER_LIBC)
1537  {
1538 #if defined(__GLIBC__)
1539  char *copy = pstrdup(collcollate);
1540  char *copy_suffix = strstr(copy, ".");
1541  bool need_version = true;
1542 
1543  /*
1544  * Check for names like C.UTF-8 by chopping off the encoding suffix on
1545  * our temporary copy, so we can skip the version.
1546  */
1547  if (copy_suffix)
1548  *copy_suffix = '\0';
1549  if (pg_strcasecmp("c", copy) == 0 ||
1550  pg_strcasecmp("posix", copy) == 0)
1551  need_version = false;
1552  pfree(copy);
1553  if (!need_version)
1554  return NULL;
1555 
1556  /* Use the glibc version because we don't have anything better. */
1557  collversion = pstrdup(gnu_get_libc_version());
1558 #elif defined(WIN32) && _WIN32_WINNT >= 0x0600
1559  /*
1560  * If we are targeting Windows Vista and above, we can ask for a name
1561  * given a collation name (earlier versions required a location code
1562  * that we don't have).
1563  */
1564  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1565  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1566 
1567  /* These would be invalid arguments, but have no version. */
1568  if (pg_strcasecmp("c", collcollate) == 0 ||
1569  pg_strcasecmp("posix", collcollate) == 0)
1570  return NULL;
1571 
1572  /* For all other names, ask the OS. */
1573  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1574  LOCALE_NAME_MAX_LENGTH);
1575  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1576  ereport(ERROR,
1577  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1578  collcollate,
1579  GetLastError())));
1580  collversion = psprintf("%d.%d,%d.%d",
1581  (version.dwNLSVersion >> 8) & 0xFFFF,
1582  version.dwNLSVersion & 0xFF,
1583  (version.dwDefinedVersion >> 8) & 0xFFFF,
1584  version.dwDefinedVersion & 0xFF);
1585 #endif
1586  }
1587 
1588  return collversion;
1589 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1186 of file pg_locale.c.

References elog, ERROR, lookup_collation_cache(), OidIsValid, 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().

1187 {
1188  /*
1189  * If we're asked about "collation 0", return false, so that the code will
1190  * go into the non-C path and report that the collation is bogus.
1191  */
1192  if (!OidIsValid(collation))
1193  return false;
1194 
1195  /*
1196  * If we're asked about the default collation, we have to inquire of the C
1197  * library. Cache the result so we only have to compute it once.
1198  */
1199  if (collation == DEFAULT_COLLATION_OID)
1200  {
1201  static int result = -1;
1202  char *localeptr;
1203 
1204  if (result >= 0)
1205  return (bool) result;
1206  localeptr = setlocale(LC_COLLATE, NULL);
1207  if (!localeptr)
1208  elog(ERROR, "invalid LC_COLLATE setting");
1209 
1210  if (strcmp(localeptr, "C") == 0)
1211  result = true;
1212  else if (strcmp(localeptr, "POSIX") == 0)
1213  result = true;
1214  else
1215  result = false;
1216  return (bool) result;
1217  }
1218 
1219  /*
1220  * If we're asked about the built-in C/POSIX collations, we know that.
1221  */
1222  if (collation == C_COLLATION_OID ||
1223  collation == POSIX_COLLATION_OID)
1224  return true;
1225 
1226  /*
1227  * Otherwise, we have to consult pg_collation, but we cache that.
1228  */
1229  return (lookup_collation_cache(collation, true))->collate_is_c;
1230 }
#define setlocale(a, b)
Definition: win32_port.h:408
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:214
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1121

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1236 of file pg_locale.c.

References elog, ereport, errcode(), errdetail(), errmsg(), ERROR, lookup_collation_cache(), OidIsValid, and setlocale.

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().

1237 {
1238  /*
1239  * If we're asked about "collation 0", return false, so that the code will
1240  * go into the non-C path and report that the collation is bogus.
1241  */
1242  if (!OidIsValid(collation))
1243  return false;
1244 
1245  /*
1246  * If we're asked about the default collation, we have to inquire of the C
1247  * library. Cache the result so we only have to compute it once.
1248  */
1249  if (collation == DEFAULT_COLLATION_OID)
1250  {
1251  static int result = -1;
1252  char *localeptr;
1253 
1254  if (result >= 0)
1255  return (bool) result;
1256  localeptr = setlocale(LC_CTYPE, NULL);
1257  if (!localeptr)
1258  elog(ERROR, "invalid LC_CTYPE setting");
1259 
1260  if (strcmp(localeptr, "C") == 0)
1261  result = true;
1262  else if (strcmp(localeptr, "POSIX") == 0)
1263  result = true;
1264  else
1265  result = false;
1266  return (bool) result;
1267  }
1268 
1269  /*
1270  * If we're asked about the built-in C/POSIX collations, we know that.
1271  */
1272  if (collation == C_COLLATION_OID ||
1273  collation == POSIX_COLLATION_OID)
1274  return true;
1275 
1276  /*
1277  * Otherwise, we have to consult pg_collation, but we cache that.
1278  */
1279  return (lookup_collation_cache(collation, true))->ctype_is_c;
1280 }
#define setlocale(a, b)
Definition: win32_port.h:408
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:214
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1121

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1333 of file pg_locale.c.

References Assert, COLLOID, 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(), 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 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().

1334 {
1335  collation_cache_entry *cache_entry;
1336 
1337  /* Callers must pass a valid OID */
1338  Assert(OidIsValid(collid));
1339 
1340  /* Return 0 for "default" collation, just in case caller forgets */
1341  if (collid == DEFAULT_COLLATION_OID)
1342  return (pg_locale_t) 0;
1343 
1344  cache_entry = lookup_collation_cache(collid, false);
1345 
1346  if (cache_entry->locale == 0)
1347  {
1348  /* We haven't computed this yet in this session, so do it */
1349  HeapTuple tp;
1350  Form_pg_collation collform;
1351  const char *collcollate;
1352  const char *collctype pg_attribute_unused();
1353  struct pg_locale_struct result;
1354  pg_locale_t resultp;
1355  Datum collversion;
1356  bool isnull;
1357 
1358  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1359  if (!HeapTupleIsValid(tp))
1360  elog(ERROR, "cache lookup failed for collation %u", collid);
1361  collform = (Form_pg_collation) GETSTRUCT(tp);
1362 
1363  collcollate = NameStr(collform->collcollate);
1364  collctype = NameStr(collform->collctype);
1365 
1366  /* We'll fill in the result struct locally before allocating memory */
1367  memset(&result, 0, sizeof(result));
1368  result.provider = collform->collprovider;
1369  result.deterministic = collform->collisdeterministic;
1370 
1371  if (collform->collprovider == COLLPROVIDER_LIBC)
1372  {
1373 #ifdef HAVE_LOCALE_T
1374  locale_t loc;
1375 
1376  if (strcmp(collcollate, collctype) == 0)
1377  {
1378  /* Normal case where they're the same */
1379  errno = 0;
1380 #ifndef WIN32
1381  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1382  NULL);
1383 #else
1384  loc = _create_locale(LC_ALL, collcollate);
1385 #endif
1386  if (!loc)
1387  report_newlocale_failure(collcollate);
1388  }
1389  else
1390  {
1391 #ifndef WIN32
1392  /* We need two newlocale() steps */
1393  locale_t loc1;
1394 
1395  errno = 0;
1396  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1397  if (!loc1)
1398  report_newlocale_failure(collcollate);
1399  errno = 0;
1400  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1401  if (!loc)
1402  report_newlocale_failure(collctype);
1403 #else
1404 
1405  /*
1406  * XXX The _create_locale() API doesn't appear to support
1407  * this. Could perhaps be worked around by changing
1408  * pg_locale_t to contain two separate fields.
1409  */
1410  ereport(ERROR,
1411  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1412  errmsg("collations with different collate and ctype values are not supported on this platform")));
1413 #endif
1414  }
1415 
1416  result.info.lt = loc;
1417 #else /* not HAVE_LOCALE_T */
1418  /* platform that doesn't support locale_t */
1419  ereport(ERROR,
1420  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1421  errmsg("collation provider LIBC is not supported on this platform")));
1422 #endif /* not HAVE_LOCALE_T */
1423  }
1424  else if (collform->collprovider == COLLPROVIDER_ICU)
1425  {
1426 #ifdef USE_ICU
1427  UCollator *collator;
1428  UErrorCode status;
1429 
1430  if (strcmp(collcollate, collctype) != 0)
1431  ereport(ERROR,
1432  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1433  errmsg("collations with different collate and ctype values are not supported by ICU")));
1434 
1435  status = U_ZERO_ERROR;
1436  collator = ucol_open(collcollate, &status);
1437  if (U_FAILURE(status))
1438  ereport(ERROR,
1439  (errmsg("could not open collator for locale \"%s\": %s",
1440  collcollate, u_errorName(status))));
1441 
1442  if (U_ICU_VERSION_MAJOR_NUM < 54)
1443  icu_set_collation_attributes(collator, collcollate);
1444 
1445  /* We will leak this string if we get an error below :-( */
1446  result.info.icu.locale = MemoryContextStrdup(TopMemoryContext,
1447  collcollate);
1448  result.info.icu.ucol = collator;
1449 #else /* not USE_ICU */
1450  /* could get here if a collation was created by a build with ICU */
1451  ereport(ERROR,
1452  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1453  errmsg("ICU is not supported in this build"), \
1454  errhint("You need to rebuild PostgreSQL using --with-icu.")));
1455 #endif /* not USE_ICU */
1456  }
1457 
1458  collversion = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1459  &isnull);
1460  if (!isnull)
1461  {
1462  char *actual_versionstr;
1463  char *collversionstr;
1464 
1465  actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
1466  if (!actual_versionstr)
1467  {
1468  /*
1469  * This could happen when specifying a version in CREATE
1470  * COLLATION for a libc locale, or manually creating a mess in
1471  * the catalogs.
1472  */
1473  ereport(ERROR,
1474  (errmsg("collation \"%s\" has no actual version, but a version was specified",
1475  NameStr(collform->collname))));
1476  }
1477  collversionstr = TextDatumGetCString(collversion);
1478 
1479  if (strcmp(actual_versionstr, collversionstr) != 0)
1480  ereport(WARNING,
1481  (errmsg("collation \"%s\" has version mismatch",
1482  NameStr(collform->collname)),
1483  errdetail("The collation in the database was created using version %s, "
1484  "but the operating system provides version %s.",
1485  collversionstr, actual_versionstr),
1486  errhint("Rebuild all objects affected by this collation and run "
1487  "ALTER COLLATION %s REFRESH VERSION, "
1488  "or build PostgreSQL with the right library version.",
1489  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1490  NameStr(collform->collname)))));
1491  }
1492 
1493  ReleaseSysCache(tp);
1494 
1495  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1496  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1497  *resultp = result;
1498 
1499  cache_entry->locale = resultp;
1500  }
1501 
1502  return cache_entry->locale;
1503 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:610
#define OidIsValid(objectId)
Definition: c.h:644
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3155
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define locale_t
Definition: win32_port.h:363
MemoryContext TopMemoryContext
Definition: mcxt.c:44
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10808
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
pg_locale_t locale
Definition: pg_locale.c:137
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
pg_attribute_unused()
Definition: isn.c:63
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
int errmsg(const char *fmt,...)
Definition: elog.c:824
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:615
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1121
Definition: pg_locale.c:131
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1510

◆ pg_perm_setlocale()

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

Definition at line 166 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, setlocale, SetMessageEncoding(), snprintf, and strlcpy().

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

167 {
168  char *result;
169  const char *envvar;
170  char *envbuf;
171 
172 #ifndef WIN32
173  result = setlocale(category, locale);
174 #else
175 
176  /*
177  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
178  * the given value is good and set it in the environment variables. We
179  * must ignore attempts to set to "", which means "keep using the old
180  * environment value".
181  */
182 #ifdef LC_MESSAGES
183  if (category == LC_MESSAGES)
184  {
185  result = (char *) locale;
186  if (locale == NULL || locale[0] == '\0')
187  return result;
188  }
189  else
190 #endif
191  result = setlocale(category, locale);
192 #endif /* WIN32 */
193 
194  if (result == NULL)
195  return result; /* fall out immediately on failure */
196 
197  /*
198  * Use the right encoding in translated messages. Under ENABLE_NLS, let
199  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
200  * format strings are ASCII, but database-encoding strings may enter the
201  * message via %s. This makes the overall message encoding equal to the
202  * database encoding.
203  */
204  if (category == LC_CTYPE)
205  {
206  static char save_lc_ctype[LC_ENV_BUFSIZE];
207 
208  /* copy setlocale() return value before callee invokes it again */
209  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
210  result = save_lc_ctype;
211 
212 #ifdef ENABLE_NLS
213  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
214 #else
216 #endif
217  }
218 
219  switch (category)
220  {
221  case LC_COLLATE:
222  envvar = "LC_COLLATE";
223  envbuf = lc_collate_envbuf;
224  break;
225  case LC_CTYPE:
226  envvar = "LC_CTYPE";
227  envbuf = lc_ctype_envbuf;
228  break;
229 #ifdef LC_MESSAGES
230  case LC_MESSAGES:
231  envvar = "LC_MESSAGES";
232  envbuf = lc_messages_envbuf;
233 #ifdef WIN32
234  result = IsoLocaleName(locale);
235  if (result == NULL)
236  result = (char *) locale;
237 #endif /* WIN32 */
238  break;
239 #endif /* LC_MESSAGES */
240  case LC_MONETARY:
241  envvar = "LC_MONETARY";
242  envbuf = lc_monetary_envbuf;
243  break;
244  case LC_NUMERIC:
245  envvar = "LC_NUMERIC";
246  envbuf = lc_numeric_envbuf;
247  break;
248  case LC_TIME:
249  envvar = "LC_TIME";
250  envbuf = lc_time_envbuf;
251  break;
252  default:
253  elog(FATAL, "unrecognized LC category: %d", category);
254  envvar = NULL; /* keep compiler quiet */
255  envbuf = NULL;
256  return NULL;
257  }
258 
259  snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
260 
261  if (putenv(envbuf))
262  return NULL;
263 
264  return result;
265 }
static char lc_numeric_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:126
void SetMessageEncoding(int encoding)
Definition: mbutils.c:1055
static char lc_monetary_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:125
#define setlocale(a, b)
Definition: win32_port.h:408
#define LC_ENV_BUFSIZE
Definition: pg_locale.c:117
static char lc_time_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:127
#define FATAL
Definition: elog.h:52
static char lc_ctype_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:120
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define putenv(x)
Definition: win32_port.h:474
#define elog(elevel,...)
Definition: elog.h:214
static char * locale
Definition: initdb.c:125
static char lc_collate_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:119
#define snprintf
Definition: port.h:192

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 498 of file pg_locale.c.

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

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

499 {
500  static struct lconv CurrentLocaleConv;
501  static bool CurrentLocaleConvAllocated = false;
502  struct lconv *extlconv;
503  struct lconv worklconv;
504  char *save_lc_monetary;
505  char *save_lc_numeric;
506 #ifdef WIN32
507  char *save_lc_ctype;
508 #endif
509 
510  /* Did we do it already? */
512  return &CurrentLocaleConv;
513 
514  /* Free any already-allocated storage */
515  if (CurrentLocaleConvAllocated)
516  {
517  free_struct_lconv(&CurrentLocaleConv);
518  CurrentLocaleConvAllocated = false;
519  }
520 
521  /*
522  * This is tricky because we really don't want to risk throwing error
523  * while the locale is set to other than our usual settings. Therefore,
524  * the process is: collect the usual settings, set locale to special
525  * setting, copy relevant data into worklconv using strdup(), restore
526  * normal settings, convert data to desired encoding, and finally stash
527  * the collected data in CurrentLocaleConv. This makes it safe if we
528  * throw an error during encoding conversion or run out of memory anywhere
529  * in the process. All data pointed to by struct lconv members is
530  * allocated with strdup, to avoid premature elog(ERROR) and to allow
531  * using a single cleanup routine.
532  */
533  memset(&worklconv, 0, sizeof(worklconv));
534 
535  /* Save prevailing values of monetary and numeric locales */
536  save_lc_monetary = setlocale(LC_MONETARY, NULL);
537  if (!save_lc_monetary)
538  elog(ERROR, "setlocale(NULL) failed");
539  save_lc_monetary = pstrdup(save_lc_monetary);
540 
541  save_lc_numeric = setlocale(LC_NUMERIC, NULL);
542  if (!save_lc_numeric)
543  elog(ERROR, "setlocale(NULL) failed");
544  save_lc_numeric = pstrdup(save_lc_numeric);
545 
546 #ifdef WIN32
547 
548  /*
549  * The POSIX standard explicitly says that it is undefined what happens if
550  * LC_MONETARY or LC_NUMERIC imply an encoding (codeset) different from
551  * that implied by LC_CTYPE. In practice, all Unix-ish platforms seem to
552  * believe that localeconv() should return strings that are encoded in the
553  * codeset implied by the LC_MONETARY or LC_NUMERIC locale name. Hence,
554  * once we have successfully collected the localeconv() results, we will
555  * convert them from that codeset to the desired server encoding.
556  *
557  * Windows, of course, resolutely does things its own way; on that
558  * platform LC_CTYPE has to match LC_MONETARY/LC_NUMERIC to get sane
559  * results. Hence, we must temporarily set that category as well.
560  */
561 
562  /* Save prevailing value of ctype locale */
563  save_lc_ctype = setlocale(LC_CTYPE, NULL);
564  if (!save_lc_ctype)
565  elog(ERROR, "setlocale(NULL) failed");
566  save_lc_ctype = pstrdup(save_lc_ctype);
567 
568  /* Here begins the critical section where we must not throw error */
569 
570  /* use numeric to set the ctype */
571  setlocale(LC_CTYPE, locale_numeric);
572 #endif
573 
574  /* Get formatting information for numeric */
575  setlocale(LC_NUMERIC, locale_numeric);
576  extlconv = localeconv();
577 
578  /* Must copy data now in case setlocale() overwrites it */
579  worklconv.decimal_point = strdup(extlconv->decimal_point);
580  worklconv.thousands_sep = strdup(extlconv->thousands_sep);
581  worklconv.grouping = strdup(extlconv->grouping);
582 
583 #ifdef WIN32
584  /* use monetary to set the ctype */
585  setlocale(LC_CTYPE, locale_monetary);
586 #endif
587 
588  /* Get formatting information for monetary */
589  setlocale(LC_MONETARY, locale_monetary);
590  extlconv = localeconv();
591 
592  /* Must copy data now in case setlocale() overwrites it */
593  worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
594  worklconv.currency_symbol = strdup(extlconv->currency_symbol);
595  worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
596  worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
597  worklconv.mon_grouping = strdup(extlconv->mon_grouping);
598  worklconv.positive_sign = strdup(extlconv->positive_sign);
599  worklconv.negative_sign = strdup(extlconv->negative_sign);
600  /* Copy scalar fields as well */
601  worklconv.int_frac_digits = extlconv->int_frac_digits;
602  worklconv.frac_digits = extlconv->frac_digits;
603  worklconv.p_cs_precedes = extlconv->p_cs_precedes;
604  worklconv.p_sep_by_space = extlconv->p_sep_by_space;
605  worklconv.n_cs_precedes = extlconv->n_cs_precedes;
606  worklconv.n_sep_by_space = extlconv->n_sep_by_space;
607  worklconv.p_sign_posn = extlconv->p_sign_posn;
608  worklconv.n_sign_posn = extlconv->n_sign_posn;
609 
610  /*
611  * Restore the prevailing locale settings; failure to do so is fatal.
612  * Possibly we could limp along with nondefault LC_MONETARY or LC_NUMERIC,
613  * but proceeding with the wrong value of LC_CTYPE would certainly be bad
614  * news; and considering that the prevailing LC_MONETARY and LC_NUMERIC
615  * are almost certainly "C", there's really no reason that restoring those
616  * should fail.
617  */
618 #ifdef WIN32
619  if (!setlocale(LC_CTYPE, save_lc_ctype))
620  elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype);
621 #endif
622  if (!setlocale(LC_MONETARY, save_lc_monetary))
623  elog(FATAL, "failed to restore LC_MONETARY to \"%s\"", save_lc_monetary);
624  if (!setlocale(LC_NUMERIC, save_lc_numeric))
625  elog(FATAL, "failed to restore LC_NUMERIC to \"%s\"", save_lc_numeric);
626 
627  /*
628  * At this point we've done our best to clean up, and can call functions
629  * that might possibly throw errors with a clean conscience. But let's
630  * make sure we don't leak any already-strdup'd fields in worklconv.
631  */
632  PG_TRY();
633  {
634  int encoding;
635 
636  /* Release the pstrdup'd locale names */
637  pfree(save_lc_monetary);
638  pfree(save_lc_numeric);
639 #ifdef WIN32
640  pfree(save_lc_ctype);
641 #endif
642 
643  /* If any of the preceding strdup calls failed, complain now. */
644  if (!struct_lconv_is_valid(&worklconv))
645  ereport(ERROR,
646  (errcode(ERRCODE_OUT_OF_MEMORY),
647  errmsg("out of memory")));
648 
649  /*
650  * Now we must perform encoding conversion from whatever's associated
651  * with the locales into the database encoding. If we can't identify
652  * the encoding implied by LC_NUMERIC or LC_MONETARY (ie we get -1),
653  * use PG_SQL_ASCII, which will result in just validating that the
654  * strings are OK in the database encoding.
655  */
657  if (encoding < 0)
658  encoding = PG_SQL_ASCII;
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  if (encoding < 0)
666  encoding = PG_SQL_ASCII;
667 
668  db_encoding_convert(encoding, &worklconv.int_curr_symbol);
669  db_encoding_convert(encoding, &worklconv.currency_symbol);
670  db_encoding_convert(encoding, &worklconv.mon_decimal_point);
671  db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
672  /* mon_grouping is not text and does not require conversion */
673  db_encoding_convert(encoding, &worklconv.positive_sign);
674  db_encoding_convert(encoding, &worklconv.negative_sign);
675  }
676  PG_CATCH();
677  {
678  free_struct_lconv(&worklconv);
679  PG_RE_THROW();
680  }
681  PG_END_TRY();
682 
683  /*
684  * Everything is good, so save the results.
685  */
686  CurrentLocaleConv = worklconv;
687  CurrentLocaleConvAllocated = true;
688  CurrentLocaleConvValid = true;
689  return &CurrentLocaleConv;
690 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:112
#define setlocale(a, b)
Definition: win32_port.h:408
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:610
char * locale_numeric
Definition: pg_locale.c:96
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:408
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_CATCH()
Definition: elog.h:305
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:437
#define PG_RE_THROW()
Definition: elog.h:336
int32 encoding
Definition: pg_database.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
#define PG_TRY()
Definition: elog.h:295
char * locale_monetary
Definition: pg_locale.c:95
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:468
#define PG_END_TRY()
Definition: elog.h:320

◆ wchar2char()

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

Definition at line 1820 of file pg_locale.c.

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

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

1821 {
1822  size_t result;
1823 
1824  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1825 
1826  if (tolen == 0)
1827  return 0;
1828 
1829 #ifdef WIN32
1830 
1831  /*
1832  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
1833  * for some reason mbstowcs and wcstombs won't do this for us, so we use
1834  * MultiByteToWideChar().
1835  */
1836  if (GetDatabaseEncoding() == PG_UTF8)
1837  {
1838  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
1839  NULL, NULL);
1840  /* A zero return is failure */
1841  if (result <= 0)
1842  result = -1;
1843  else
1844  {
1845  Assert(result <= tolen);
1846  /* Microsoft counts the zero terminator in the result */
1847  result--;
1848  }
1849  }
1850  else
1851 #endif /* WIN32 */
1852  if (locale == (pg_locale_t) 0)
1853  {
1854  /* Use wcstombs directly for the default locale */
1855  result = wcstombs(to, from, tolen);
1856  }
1857  else
1858  {
1859 #ifdef HAVE_LOCALE_T
1860 #ifdef HAVE_WCSTOMBS_L
1861  /* Use wcstombs_l for nondefault locales */
1862  result = wcstombs_l(to, from, tolen, locale->info.lt);
1863 #else /* !HAVE_WCSTOMBS_L */
1864  /* We have to temporarily set the locale as current ... ugh */
1865  locale_t save_locale = uselocale(locale->info.lt);
1866 
1867  result = wcstombs(to, from, tolen);
1868 
1869  uselocale(save_locale);
1870 #endif /* HAVE_WCSTOMBS_L */
1871 #else /* !HAVE_LOCALE_T */
1872  /* Can't have locale != 0 without HAVE_LOCALE_T */
1873  elog(ERROR, "wcstombs_l is not available");
1874  result = 0; /* keep compiler quiet */
1875 #endif /* HAVE_LOCALE_T */
1876  }
1877 
1878  return result;
1879 }
#define wcstombs_l
Definition: win32_port.h:389
#define ERROR
Definition: elog.h:43
#define locale_t
Definition: win32_port.h:363
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
#define Assert(condition)
Definition: c.h:738
#define elog(elevel,...)
Definition: elog.h:214
union pg_locale_struct::@142 info

Variable Documentation

◆ locale_messages

char* locale_messages

Definition at line 94 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 95 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 96 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 97 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[]

Definition at line 106 of file pg_locale.c.

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

◆ localized_abbrev_months

char* localized_abbrev_months[]

Definition at line 108 of file pg_locale.c.

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

◆ localized_full_days

char* localized_full_days[]

Definition at line 107 of file pg_locale.c.

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

◆ localized_full_months

char* localized_full_months[]

Definition at line 109 of file pg_locale.c.

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