PostgreSQL Source Code  git master
pg_locale.c File Reference
#include "postgres.h"
#include <time.h>
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_control.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/hsearch.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/syscache.h"
Include dependency graph for pg_locale.c:

Go to the source code of this file.

Data Structures

struct  collation_cache_entry
 

Macros

#define MAX_L10N_DATA   80
 

Functions

char * pg_perm_setlocale (int category, const char *locale)
 
bool check_locale (int category, const char *locale, char **canonname)
 
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_messages (char **newval, void **extra, GucSource source)
 
void assign_locale_messages (const char *newval, void *extra)
 
static void free_struct_lconv (struct lconv *s)
 
static bool struct_lconv_is_valid (struct lconv *s)
 
static void db_encoding_convert (int encoding, char **str)
 
struct lconv * PGLC_localeconv (void)
 
static void cache_single_string (char **dst, const char *src, int encoding)
 
void cache_locale_time (void)
 
void check_strxfrm_bug (void)
 
static collation_cache_entrylookup_collation_cache (Oid collation, bool set_flags)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
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 [7+1]
 
char * localized_full_days [7+1]
 
char * localized_abbrev_months [12+1]
 
char * localized_full_months [12+1]
 
static bool CurrentLocaleConvValid = false
 
static bool CurrentLCTimeValid = false
 
static HTABcollation_cache = NULL
 

Macro Definition Documentation

◆ MAX_L10N_DATA

#define MAX_L10N_DATA   80

Definition at line 81 of file pg_locale.c.

Referenced by cache_locale_time(), and PGLC_localeconv().

Function Documentation

◆ assign_locale_messages()

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

Definition at line 358 of file pg_locale.c.

References pg_perm_setlocale().

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

◆ assign_locale_monetary()

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

Definition at line 295 of file pg_locale.c.

References CurrentLocaleConvValid.

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

◆ assign_locale_numeric()

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

Definition at line 307 of file pg_locale.c.

References CurrentLocaleConvValid.

308 {
309  CurrentLocaleConvValid = false;
310 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:103

◆ assign_locale_time()

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

Definition at line 319 of file pg_locale.c.

References CurrentLCTimeValid.

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

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 747 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_mbstrlen(), PG_SQL_ASCII, pg_strcasecmp(), PG_UTF8, pstrdup(), setlocale, tm, and wchar2char().

Referenced by DCH_from_char(), and DCH_to_char().

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

◆ cache_single_string()

static void cache_single_string ( char **  dst,
const char *  src,
int  encoding 
)
static

Definition at line 724 of file pg_locale.c.

References MemoryContextStrdup(), pfree(), pg_any_to_server(), and TopMemoryContext.

Referenced by cache_locale_time().

725 {
726  char *ptr;
727  char *olddst;
728 
729  /* Convert the string to the database encoding, or validate it's OK */
730  ptr = pg_any_to_server(src, strlen(src), encoding);
731 
732  /* Store the string in long-lived storage, replacing any previous value */
733  olddst = *dst;
735  if (olddst)
736  pfree(olddst);
737 
738  /* Might as well clean up any palloc'd conversion result, too */
739  if (ptr != src)
740  pfree(ptr);
741 }
void pfree(void *pointer)
Definition: mcxt.c:1169
MemoryContext TopMemoryContext
Definition: mcxt.c:48
int32 encoding
Definition: pg_database.h:41
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:676

◆ char2wchar()

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

Definition at line 2032 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().

2034 {
2035  size_t result;
2036 
2037  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2038 
2039  if (tolen == 0)
2040  return 0;
2041 
2042 #ifdef WIN32
2043  /* See WIN32 "Unicode" comment above */
2044  if (GetDatabaseEncoding() == PG_UTF8)
2045  {
2046  /* Win32 API does not work for zero-length input */
2047  if (fromlen == 0)
2048  result = 0;
2049  else
2050  {
2051  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
2052  /* A zero return is failure */
2053  if (result == 0)
2054  result = -1;
2055  }
2056 
2057  if (result != -1)
2058  {
2059  Assert(result < tolen);
2060  /* Append trailing null wchar (MultiByteToWideChar() does not) */
2061  to[result] = 0;
2062  }
2063  }
2064  else
2065 #endif /* WIN32 */
2066  {
2067  /* mbstowcs requires ending '\0' */
2068  char *str = pnstrdup(from, fromlen);
2069 
2070  if (locale == (pg_locale_t) 0)
2071  {
2072  /* Use mbstowcs directly for the default locale */
2073  result = mbstowcs(to, str, tolen);
2074  }
2075  else
2076  {
2077 #ifdef HAVE_LOCALE_T
2078 #ifdef HAVE_MBSTOWCS_L
2079  /* Use mbstowcs_l for nondefault locales */
2080  result = mbstowcs_l(to, str, tolen, locale->info.lt);
2081 #else /* !HAVE_MBSTOWCS_L */
2082  /* We have to temporarily set the locale as current ... ugh */
2083  locale_t save_locale = uselocale(locale->info.lt);
2084 
2085  result = mbstowcs(to, str, tolen);
2086 
2087  uselocale(save_locale);
2088 #endif /* HAVE_MBSTOWCS_L */
2089 #else /* !HAVE_LOCALE_T */
2090  /* Can't have locale != 0 without HAVE_LOCALE_T */
2091  elog(ERROR, "mbstowcs_l is not available");
2092  result = 0; /* keep compiler quiet */
2093 #endif /* HAVE_LOCALE_T */
2094  }
2095 
2096  pfree(str);
2097  }
2098 
2099  if (result == -1)
2100  {
2101  /*
2102  * Invalid multibyte character encountered. We try to give a useful
2103  * error message by letting pg_verifymbstr check the string. But it's
2104  * possible that the string is OK to us, and not OK to mbstowcs ---
2105  * this suggests that the LC_CTYPE locale is different from the
2106  * database encoding. Give a generic error message if pg_verifymbstr
2107  * can't find anything wrong.
2108  */
2109  pg_verifymbstr(from, fromlen, false); /* might not return */
2110  /* but if it does ... */
2111  ereport(ERROR,
2112  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
2113  errmsg("invalid multibyte character for locale"),
2114  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
2115  }
2116 
2117  return result;
2118 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
int errcode(int sqlerrcode)
Definition: elog.c:698
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
#define locale_t
Definition: win32_port.h:391
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1505
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define mbstowcs_l
Definition: win32_port.h:418
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
union pg_locale_struct::@142 info

◆ check_locale()

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

Definition at line 246 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().

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

◆ check_locale_messages()

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

Definition at line 335 of file pg_locale.c.

References check_locale(), and PGC_S_DEFAULT.

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

◆ check_locale_monetary()

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

Definition at line 289 of file pg_locale.c.

References check_locale().

290 {
291  return check_locale(LC_MONETARY, *newval, NULL);
292 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:246
#define newval

◆ check_locale_numeric()

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

Definition at line 301 of file pg_locale.c.

References check_locale().

302 {
303  return check_locale(LC_NUMERIC, *newval, NULL);
304 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:246
#define newval

◆ check_locale_time()

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

Definition at line 313 of file pg_locale.c.

References check_locale().

314 {
315  return check_locale(LC_TIME, *newval, NULL);
316 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:246
#define newval

◆ check_strxfrm_bug()

void check_strxfrm_bug ( void  )

Definition at line 1187 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

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

◆ db_encoding_convert()

static void db_encoding_convert ( int  encoding,
char **  str 
)
static

Definition at line 435 of file pg_locale.c.

References ereport, errcode(), errmsg(), ERROR, free, pfree(), and pg_any_to_server().

Referenced by PGLC_localeconv().

436 {
437  char *pstr;
438  char *mstr;
439 
440  /* convert the string to the database encoding */
441  pstr = pg_any_to_server(*str, strlen(*str), encoding);
442  if (pstr == *str)
443  return; /* no conversion happened */
444 
445  /* need it malloc'd not palloc'd */
446  mstr = strdup(pstr);
447  if (mstr == NULL)
448  ereport(ERROR,
449  (errcode(ERRCODE_OUT_OF_MEMORY),
450  errmsg("out of memory")));
451 
452  /* replace old string */
453  free(*str);
454  *str = mstr;
455 
456  pfree(pstr);
457 }
int errcode(int sqlerrcode)
Definition: elog.c:698
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
#define free(a)
Definition: header.h:65
int32 encoding
Definition: pg_database.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:676

◆ free_struct_lconv()

static void free_struct_lconv ( struct lconv *  s)
static

Definition at line 375 of file pg_locale.c.

References free.

Referenced by PGLC_localeconv().

376 {
377  if (s->decimal_point)
378  free(s->decimal_point);
379  if (s->thousands_sep)
380  free(s->thousands_sep);
381  if (s->grouping)
382  free(s->grouping);
383  if (s->int_curr_symbol)
384  free(s->int_curr_symbol);
385  if (s->currency_symbol)
386  free(s->currency_symbol);
387  if (s->mon_decimal_point)
388  free(s->mon_decimal_point);
389  if (s->mon_thousands_sep)
390  free(s->mon_thousands_sep);
391  if (s->mon_grouping)
392  free(s->mon_grouping);
393  if (s->positive_sign)
394  free(s->positive_sign);
395  if (s->negative_sign)
396  free(s->negative_sign);
397 }
#define free(a)
Definition: header.h:65

◆ get_collation_actual_version()

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

Definition at line 1645 of file pg_locale.c.

References asc_tolower(), buf, ereport, errcode(), errmsg(), ERROR, get_encoding_name_for_icu(), GetDatabaseEncoding(), locale_t, name, palloc(), pg_attribute_unused(), pg_encoding_to_char(), pg_strcasecmp(), pg_strncasecmp(), 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().

1646 {
1647  char *collversion = NULL;
1648 
1649 #ifdef USE_ICU
1650  if (collprovider == COLLPROVIDER_ICU)
1651  {
1652  UCollator *collator;
1653  UErrorCode status;
1654  UVersionInfo versioninfo;
1655  char buf[U_MAX_VERSION_STRING_LENGTH];
1656 
1657  status = U_ZERO_ERROR;
1658  collator = ucol_open(collcollate, &status);
1659  if (U_FAILURE(status))
1660  ereport(ERROR,
1661  (errmsg("could not open collator for locale \"%s\": %s",
1662  collcollate, u_errorName(status))));
1663  ucol_getVersion(collator, versioninfo);
1664  ucol_close(collator);
1665 
1666  u_versionToString(versioninfo, buf);
1667  collversion = pstrdup(buf);
1668  }
1669  else
1670 #endif
1671  if (collprovider == COLLPROVIDER_LIBC &&
1672  pg_strcasecmp("C", collcollate) != 0 &&
1673  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1674  pg_strcasecmp("POSIX", collcollate) != 0)
1675  {
1676 #if defined(__GLIBC__)
1677  /* Use the glibc version because we don't have anything better. */
1678  collversion = pstrdup(gnu_get_libc_version());
1679 #elif defined(LC_VERSION_MASK)
1680  locale_t loc;
1681 
1682  /* Look up FreeBSD collation version. */
1683  loc = newlocale(LC_COLLATE, collcollate, NULL);
1684  if (loc)
1685  {
1686  collversion =
1687  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1688  freelocale(loc);
1689  }
1690  else
1691  ereport(ERROR,
1692  (errmsg("could not load locale \"%s\"", collcollate)));
1693 #elif defined(WIN32) && _WIN32_WINNT >= 0x0600
1694  /*
1695  * If we are targeting Windows Vista and above, we can ask for a name
1696  * given a collation name (earlier versions required a location code
1697  * that we don't have).
1698  */
1699  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1700  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1701 
1702  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1703  LOCALE_NAME_MAX_LENGTH);
1704  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1705  {
1706  /*
1707  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1708  * locale name like "English_United States.1252". Until those
1709  * values can be prevented from entering the system, or 100%
1710  * reliably converted to the more useful tag format, tolerate the
1711  * resulting error and report that we have no version data.
1712  */
1713  if (GetLastError() == ERROR_INVALID_PARAMETER)
1714  return NULL;
1715 
1716  ereport(ERROR,
1717  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1718  collcollate,
1719  GetLastError())));
1720  }
1721  collversion = psprintf("%d.%d,%d.%d",
1722  (version.dwNLSVersion >> 8) & 0xFFFF,
1723  version.dwNLSVersion & 0xFF,
1724  (version.dwDefinedVersion >> 8) & 0xFFFF,
1725  version.dwDefinedVersion & 0xFF);
1726 #endif
1727  }
1728 
1729  return collversion;
1730 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
#define ERROR
Definition: elog.h:46
static char * buf
Definition: pg_test_fsync.c:68
#define locale_t
Definition: win32_port.h:391
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1321 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().

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

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1371 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().

1372 {
1373  /*
1374  * If we're asked about "collation 0", return false, so that the code will
1375  * go into the non-C path and report that the collation is bogus.
1376  */
1377  if (!OidIsValid(collation))
1378  return false;
1379 
1380  /*
1381  * If we're asked about the default collation, we have to inquire of the C
1382  * library. Cache the result so we only have to compute it once.
1383  */
1384  if (collation == DEFAULT_COLLATION_OID)
1385  {
1386  static int result = -1;
1387  char *localeptr;
1388 
1389  if (result >= 0)
1390  return (bool) result;
1391  localeptr = setlocale(LC_CTYPE, NULL);
1392  if (!localeptr)
1393  elog(ERROR, "invalid LC_CTYPE setting");
1394 
1395  if (strcmp(localeptr, "C") == 0)
1396  result = true;
1397  else if (strcmp(localeptr, "POSIX") == 0)
1398  result = true;
1399  else
1400  result = false;
1401  return (bool) result;
1402  }
1403 
1404  /*
1405  * If we're asked about the built-in C/POSIX collations, we know that.
1406  */
1407  if (collation == C_COLLATION_OID ||
1408  collation == POSIX_COLLATION_OID)
1409  return true;
1410 
1411  /*
1412  * Otherwise, we have to consult pg_collation, but we cache that.
1413  */
1414  return (lookup_collation_cache(collation, true))->ctype_is_c;
1415 }
#define setlocale(a, b)
Definition: win32_port.h:436
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
#define elog(elevel,...)
Definition: elog.h:232
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1257

◆ lookup_collation_cache()

static collation_cache_entry* lookup_collation_cache ( Oid  collation,
bool  set_flags 
)
static

Definition at line 1257 of file pg_locale.c.

References Assert, collation_cache_entry::collate_is_c, COLLOID, collation_cache_entry::ctype_is_c, elog, HASHCTL::entrysize, ERROR, collation_cache_entry::flags_valid, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, HASHCTL::keysize, collation_cache_entry::locale, NameStr, ObjectIdGetDatum, OidIsValid, ReleaseSysCache(), and SearchSysCache1().

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

1258 {
1259  collation_cache_entry *cache_entry;
1260  bool found;
1261 
1262  Assert(OidIsValid(collation));
1263  Assert(collation != DEFAULT_COLLATION_OID);
1264 
1265  if (collation_cache == NULL)
1266  {
1267  /* First time through, initialize the hash table */
1268  HASHCTL ctl;
1269 
1270  ctl.keysize = sizeof(Oid);
1271  ctl.entrysize = sizeof(collation_cache_entry);
1272  collation_cache = hash_create("Collation cache", 100, &ctl,
1273  HASH_ELEM | HASH_BLOBS);
1274  }
1275 
1276  cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
1277  if (!found)
1278  {
1279  /*
1280  * Make sure cache entry is marked invalid, in case we fail before
1281  * setting things.
1282  */
1283  cache_entry->flags_valid = false;
1284  cache_entry->locale = 0;
1285  }
1286 
1287  if (set_flags && !cache_entry->flags_valid)
1288  {
1289  /* Attempt to set the flags */
1290  HeapTuple tp;
1291  Form_pg_collation collform;
1292  const char *collcollate;
1293  const char *collctype;
1294 
1295  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1296  if (!HeapTupleIsValid(tp))
1297  elog(ERROR, "cache lookup failed for collation %u", collation);
1298  collform = (Form_pg_collation) GETSTRUCT(tp);
1299 
1300  collcollate = NameStr(collform->collcollate);
1301  collctype = NameStr(collform->collctype);
1302 
1303  cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) ||
1304  (strcmp(collcollate, "POSIX") == 0));
1305  cache_entry->ctype_is_c = ((strcmp(collctype, "C") == 0) ||
1306  (strcmp(collctype, "POSIX") == 0));
1307 
1308  cache_entry->flags_valid = true;
1309 
1310  ReleaseSysCache(tp);
1311  }
1312 
1313  return cache_entry;
1314 }
bool flags_valid
Definition: pg_locale.c:113
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define HASH_ELEM
Definition: hsearch.h:95
bool ctype_is_c
Definition: pg_locale.c:112
Size entrysize
Definition: hsearch.h:76
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
bool collate_is_c
Definition: pg_locale.c:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
pg_locale_t locale
Definition: pg_locale.c:114
#define HASH_BLOBS
Definition: hsearch.h:97
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Size keysize
Definition: hsearch.h:75
static HTAB * collation_cache
Definition: pg_locale.c:117
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:56
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Definition: pg_locale.c:108

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1468 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().

1469 {
1470  collation_cache_entry *cache_entry;
1471 
1472  /* Callers must pass a valid OID */
1473  Assert(OidIsValid(collid));
1474 
1475  /* Return 0 for "default" collation, just in case caller forgets */
1476  if (collid == DEFAULT_COLLATION_OID)
1477  return (pg_locale_t) 0;
1478 
1479  cache_entry = lookup_collation_cache(collid, false);
1480 
1481  if (cache_entry->locale == 0)
1482  {
1483  /* We haven't computed this yet in this session, so do it */
1484  HeapTuple tp;
1485  Form_pg_collation collform;
1486  const char *collcollate;
1487  const char *collctype pg_attribute_unused();
1488  struct pg_locale_struct result;
1489  pg_locale_t resultp;
1490  Datum collversion;
1491  bool isnull;
1492 
1493  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1494  if (!HeapTupleIsValid(tp))
1495  elog(ERROR, "cache lookup failed for collation %u", collid);
1496  collform = (Form_pg_collation) GETSTRUCT(tp);
1497 
1498  collcollate = NameStr(collform->collcollate);
1499  collctype = NameStr(collform->collctype);
1500 
1501  /* We'll fill in the result struct locally before allocating memory */
1502  memset(&result, 0, sizeof(result));
1503  result.provider = collform->collprovider;
1504  result.deterministic = collform->collisdeterministic;
1505 
1506  if (collform->collprovider == COLLPROVIDER_LIBC)
1507  {
1508 #ifdef HAVE_LOCALE_T
1509  locale_t loc;
1510 
1511  if (strcmp(collcollate, collctype) == 0)
1512  {
1513  /* Normal case where they're the same */
1514  errno = 0;
1515 #ifndef WIN32
1516  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1517  NULL);
1518 #else
1519  loc = _create_locale(LC_ALL, collcollate);
1520 #endif
1521  if (!loc)
1522  report_newlocale_failure(collcollate);
1523  }
1524  else
1525  {
1526 #ifndef WIN32
1527  /* We need two newlocale() steps */
1528  locale_t loc1;
1529 
1530  errno = 0;
1531  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1532  if (!loc1)
1533  report_newlocale_failure(collcollate);
1534  errno = 0;
1535  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1536  if (!loc)
1537  report_newlocale_failure(collctype);
1538 #else
1539 
1540  /*
1541  * XXX The _create_locale() API doesn't appear to support
1542  * this. Could perhaps be worked around by changing
1543  * pg_locale_t to contain two separate fields.
1544  */
1545  ereport(ERROR,
1546  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1547  errmsg("collations with different collate and ctype values are not supported on this platform")));
1548 #endif
1549  }
1550 
1551  result.info.lt = loc;
1552 #else /* not HAVE_LOCALE_T */
1553  /* platform that doesn't support locale_t */
1554  ereport(ERROR,
1555  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1556  errmsg("collation provider LIBC is not supported on this platform")));
1557 #endif /* not HAVE_LOCALE_T */
1558  }
1559  else if (collform->collprovider == COLLPROVIDER_ICU)
1560  {
1561 #ifdef USE_ICU
1562  UCollator *collator;
1563  UErrorCode status;
1564 
1565  if (strcmp(collcollate, collctype) != 0)
1566  ereport(ERROR,
1567  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1568  errmsg("collations with different collate and ctype values are not supported by ICU")));
1569 
1570  status = U_ZERO_ERROR;
1571  collator = ucol_open(collcollate, &status);
1572  if (U_FAILURE(status))
1573  ereport(ERROR,
1574  (errmsg("could not open collator for locale \"%s\": %s",
1575  collcollate, u_errorName(status))));
1576 
1577  if (U_ICU_VERSION_MAJOR_NUM < 54)
1578  icu_set_collation_attributes(collator, collcollate);
1579 
1580  /* We will leak this string if we get an error below :-( */
1581  result.info.icu.locale = MemoryContextStrdup(TopMemoryContext,
1582  collcollate);
1583  result.info.icu.ucol = collator;
1584 #else /* not USE_ICU */
1585  /* could get here if a collation was created by a build with ICU */
1586  ereport(ERROR,
1587  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1588  errmsg("ICU is not supported in this build"), \
1589  errhint("You need to rebuild PostgreSQL using %s.", "--with-icu")));
1590 #endif /* not USE_ICU */
1591  }
1592 
1593  collversion = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1594  &isnull);
1595  if (!isnull)
1596  {
1597  char *actual_versionstr;
1598  char *collversionstr;
1599 
1600  actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
1601  if (!actual_versionstr)
1602  {
1603  /*
1604  * This could happen when specifying a version in CREATE
1605  * COLLATION for a libc locale, or manually creating a mess in
1606  * the catalogs.
1607  */
1608  ereport(ERROR,
1609  (errmsg("collation \"%s\" has no actual version, but a version was specified",
1610  NameStr(collform->collname))));
1611  }
1612  collversionstr = TextDatumGetCString(collversion);
1613 
1614  if (strcmp(actual_versionstr, collversionstr) != 0)
1615  ereport(WARNING,
1616  (errmsg("collation \"%s\" has version mismatch",
1617  NameStr(collform->collname)),
1618  errdetail("The collation in the database was created using version %s, "
1619  "but the operating system provides version %s.",
1620  collversionstr, actual_versionstr),
1621  errhint("Rebuild all objects affected by this collation and run "
1622  "ALTER COLLATION %s REFRESH VERSION, "
1623  "or build PostgreSQL with the right library version.",
1624  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1625  NameStr(collform->collname)))));
1626  }
1627 
1628  ReleaseSysCache(tp);
1629 
1630  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1631  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1632  *resultp = result;
1633 
1634  cache_entry->locale = resultp;
1635  }
1636 
1637  return cache_entry->locale;
1638 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
int errcode(int sqlerrcode)
Definition: elog.c:698
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define locale_t
Definition: win32_port.h:391
MemoryContext TopMemoryContext
Definition: mcxt.c:48
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11416
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
pg_locale_t locale
Definition: pg_locale.c:114
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
pg_attribute_unused()
Definition: isn.c:63
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:56
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1257
Definition: pg_locale.c:108
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1645

◆ pg_perm_setlocale()

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

Definition at line 143 of file pg_locale.c.

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

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

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

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 465 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().

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

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 404 of file pg_locale.c.

Referenced by PGLC_localeconv().

405 {
406  if (s->decimal_point == NULL)
407  return false;
408  if (s->thousands_sep == NULL)
409  return false;
410  if (s->grouping == NULL)
411  return false;
412  if (s->int_curr_symbol == NULL)
413  return false;
414  if (s->currency_symbol == NULL)
415  return false;
416  if (s->mon_decimal_point == NULL)
417  return false;
418  if (s->mon_thousands_sep == NULL)
419  return false;
420  if (s->mon_grouping == NULL)
421  return false;
422  if (s->positive_sign == NULL)
423  return false;
424  if (s->negative_sign == NULL)
425  return false;
426  return true;
427 }

◆ wchar2char()

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

Definition at line 1961 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().

1962 {
1963  size_t result;
1964 
1965  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1966 
1967  if (tolen == 0)
1968  return 0;
1969 
1970 #ifdef WIN32
1971 
1972  /*
1973  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
1974  * for some reason mbstowcs and wcstombs won't do this for us, so we use
1975  * MultiByteToWideChar().
1976  */
1977  if (GetDatabaseEncoding() == PG_UTF8)
1978  {
1979  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
1980  NULL, NULL);
1981  /* A zero return is failure */
1982  if (result <= 0)
1983  result = -1;
1984  else
1985  {
1986  Assert(result <= tolen);
1987  /* Microsoft counts the zero terminator in the result */
1988  result--;
1989  }
1990  }
1991  else
1992 #endif /* WIN32 */
1993  if (locale == (pg_locale_t) 0)
1994  {
1995  /* Use wcstombs directly for the default locale */
1996  result = wcstombs(to, from, tolen);
1997  }
1998  else
1999  {
2000 #ifdef HAVE_LOCALE_T
2001 #ifdef HAVE_WCSTOMBS_L
2002  /* Use wcstombs_l for nondefault locales */
2003  result = wcstombs_l(to, from, tolen, locale->info.lt);
2004 #else /* !HAVE_WCSTOMBS_L */
2005  /* We have to temporarily set the locale as current ... ugh */
2006  locale_t save_locale = uselocale(locale->info.lt);
2007 
2008  result = wcstombs(to, from, tolen);
2009 
2010  uselocale(save_locale);
2011 #endif /* HAVE_WCSTOMBS_L */
2012 #else /* !HAVE_LOCALE_T */
2013  /* Can't have locale != 0 without HAVE_LOCALE_T */
2014  elog(ERROR, "wcstombs_l is not available");
2015  result = 0; /* keep compiler quiet */
2016 #endif /* HAVE_LOCALE_T */
2017  }
2018 
2019  return result;
2020 }
#define wcstombs_l
Definition: win32_port.h:417
#define ERROR
Definition: elog.h:46
#define locale_t
Definition: win32_port.h:391
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
union pg_locale_struct::@142 info

Variable Documentation

◆ collation_cache

HTAB* collation_cache = NULL
static

Definition at line 117 of file pg_locale.c.

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 104 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 103 of file pg_locale.c.

Referenced by assign_locale_monetary(), assign_locale_numeric(), and PGLC_localeconv().

◆ locale_messages

char* locale_messages

Definition at line 85 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 86 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 87 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 88 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 97 of file pg_locale.c.

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

◆ localized_abbrev_months

char* localized_abbrev_months[12+1]

Definition at line 99 of file pg_locale.c.

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

◆ localized_full_days

char* localized_full_days[7+1]

Definition at line 98 of file pg_locale.c.

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

◆ localized_full_months

char* localized_full_months[12+1]

Definition at line 100 of file pg_locale.c.

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