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 "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/guc_hooks.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 PGLOCALE_SUPPORT_ERROR(provider)    elog(ERROR, "unsupported collprovider for %s: %c", __func__, provider)
 
#define TEXTBUFLEN   1024
 
#define MAX_L10N_DATA   80
 

Functions

static size_t mbstowcs_l (wchar_t *dest, const char *src, size_t n, locale_t loc)
 
static size_t wcstombs_l (char *dest, const wchar_t *src, size_t n, locale_t loc)
 
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)
 
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)
 
void make_icu_collator (const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
 
static void report_newlocale_failure (const char *localename)
 
bool pg_locale_deterministic (pg_locale_t locale)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
static int pg_strcoll_libc (const char *arg1, const char *arg2, pg_locale_t locale)
 
static int pg_strncoll_libc (const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
 
int pg_strcoll (const char *arg1, const char *arg2, pg_locale_t locale)
 
int pg_strncoll (const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
 
static size_t pg_strxfrm_libc (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
static size_t pg_strnxfrm_libc (char *dest, const char *src, size_t srclen, size_t destsize, pg_locale_t locale)
 
bool pg_strxfrm_enabled (pg_locale_t locale)
 
size_t pg_strxfrm (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
size_t pg_strnxfrm (char *dest, size_t destsize, const char *src, size_t srclen, pg_locale_t locale)
 
bool pg_strxfrm_prefix_enabled (pg_locale_t locale)
 
size_t pg_strxfrm_prefix (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
size_t pg_strnxfrm_prefix (char *dest, size_t destsize, const char *src, size_t srclen, pg_locale_t locale)
 
int builtin_locale_encoding (const char *locale)
 
const char * builtin_validate_locale (int encoding, const char *locale)
 
char * icu_language_tag (const char *loc_str, int elevel)
 
void icu_validate_locale (const char *loc_str)
 
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
 
int icu_validation_level = WARNING
 
char * localized_abbrev_days [7+1]
 
char * localized_full_days [7+1]
 
char * localized_abbrev_months [12+1]
 
char * localized_full_months [12+1]
 
bool database_ctype_is_c = false
 
static bool CurrentLocaleConvValid = false
 
static bool CurrentLCTimeValid = false
 
static HTABcollation_cache = NULL
 
struct pg_locale_struct default_locale
 

Macro Definition Documentation

◆ MAX_L10N_DATA

#define MAX_L10N_DATA   80

Definition at line 93 of file pg_locale.c.

◆ PGLOCALE_SUPPORT_ERROR

#define PGLOCALE_SUPPORT_ERROR (   provider)     elog(ERROR, "unsupported collprovider for %s: %c", __func__, provider)

Definition at line 84 of file pg_locale.c.

◆ TEXTBUFLEN

#define TEXTBUFLEN   1024

Definition at line 91 of file pg_locale.c.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 427 of file pg_locale.c.

428 {
429  /*
430  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
431  * We ignore failure, as per comment above.
432  */
433 #ifdef LC_MESSAGES
434  (void) pg_perm_setlocale(LC_MESSAGES, newval);
435 #endif
436 }
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:212

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 364 of file pg_locale.c.

365 {
366  CurrentLocaleConvValid = false;
367 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:120

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 376 of file pg_locale.c.

377 {
378  CurrentLocaleConvValid = false;
379 }

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 388 of file pg_locale.c.

389 {
390  CurrentLCTimeValid = false;
391 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:121

References CurrentLCTimeValid.

◆ builtin_locale_encoding()

int builtin_locale_encoding ( const char *  locale)

Definition at line 2517 of file pg_locale.c.

2518 {
2519  if (strcmp(locale, "C") == 0)
2520  return -1;
2521  if (strcmp(locale, "C.UTF-8") == 0)
2522  return PG_UTF8;
2523 
2524  ereport(ERROR,
2525  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2526  errmsg("invalid locale name \"%s\" for builtin provider",
2527  locale)));
2528 
2529  return 0; /* keep compiler quiet */
2530 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static char * locale
Definition: initdb.c:140
@ PG_UTF8
Definition: pg_wchar.h:232

References ereport, errcode(), errmsg(), ERROR, locale, and PG_UTF8.

Referenced by builtin_validate_locale(), and DefineCollation().

◆ builtin_validate_locale()

const char* builtin_validate_locale ( int  encoding,
const char *  locale 
)

Definition at line 2541 of file pg_locale.c.

2542 {
2543  const char *canonical_name = NULL;
2544  int required_encoding;
2545 
2546  if (strcmp(locale, "C") == 0)
2547  canonical_name = "C";
2548  else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0)
2549  canonical_name = "C.UTF-8";
2550 
2551  if (!canonical_name)
2552  ereport(ERROR,
2553  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2554  errmsg("invalid locale name \"%s\" for builtin provider",
2555  locale)));
2556 
2557  required_encoding = builtin_locale_encoding(canonical_name);
2558  if (required_encoding >= 0 && encoding != required_encoding)
2559  ereport(ERROR,
2560  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2561  errmsg("encoding \"%s\" does not match locale \"%s\"",
2563 
2564  return canonical_name;
2565 }
int32 encoding
Definition: pg_database.h:41
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:2517
#define pg_encoding_to_char
Definition: pg_wchar.h:630

References builtin_locale_encoding(), encoding, ereport, errcode(), errmsg(), ERROR, locale, and pg_encoding_to_char.

Referenced by CheckMyDatabase(), createdb(), DefineCollation(), and pg_newlocale_from_collation().

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 806 of file pg_locale.c.

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

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

Referenced by DCH_from_char(), and DCH_to_char().

◆ cache_single_string()

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

Definition at line 783 of file pg_locale.c.

784 {
785  char *ptr;
786  char *olddst;
787 
788  /* Convert the string to the database encoding, or validate it's OK */
789  ptr = pg_any_to_server(src, strlen(src), encoding);
790 
791  /* Store the string in long-lived storage, replacing any previous value */
792  olddst = *dst;
794  if (olddst)
795  pfree(olddst);
796 
797  /* Might as well clean up any palloc'd conversion result, too */
798  if (ptr != src)
799  pfree(ptr);
800 }
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:676
MemoryContext TopMemoryContext
Definition: mcxt.c:137
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1670

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

Referenced by cache_locale_time().

◆ char2wchar()

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

Definition at line 3111 of file pg_locale.c.

3113 {
3114  size_t result;
3115 
3116  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
3117 
3118  if (tolen == 0)
3119  return 0;
3120 
3121 #ifdef WIN32
3122  /* See WIN32 "Unicode" comment above */
3123  if (GetDatabaseEncoding() == PG_UTF8)
3124  {
3125  /* Win32 API does not work for zero-length input */
3126  if (fromlen == 0)
3127  result = 0;
3128  else
3129  {
3130  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
3131  /* A zero return is failure */
3132  if (result == 0)
3133  result = -1;
3134  }
3135 
3136  if (result != -1)
3137  {
3138  Assert(result < tolen);
3139  /* Append trailing null wchar (MultiByteToWideChar() does not) */
3140  to[result] = 0;
3141  }
3142  }
3143  else
3144 #endif /* WIN32 */
3145  {
3146  /* mbstowcs requires ending '\0' */
3147  char *str = pnstrdup(from, fromlen);
3148 
3149  if (locale == (pg_locale_t) 0)
3150  {
3151  /* Use mbstowcs directly for the default locale */
3152  result = mbstowcs(to, str, tolen);
3153  }
3154  else
3155  {
3156  /* Use mbstowcs_l for nondefault locales */
3157  result = mbstowcs_l(to, str, tolen, locale->info.lt);
3158  }
3159 
3160  pfree(str);
3161  }
3162 
3163  if (result == -1)
3164  {
3165  /*
3166  * Invalid multibyte character encountered. We try to give a useful
3167  * error message by letting pg_verifymbstr check the string. But it's
3168  * possible that the string is OK to us, and not OK to mbstowcs ---
3169  * this suggests that the LC_CTYPE locale is different from the
3170  * database encoding. Give a generic error message if pg_verifymbstr
3171  * can't find anything wrong.
3172  */
3173  pg_verifymbstr(from, fromlen, false); /* might not return */
3174  /* but if it does ... */
3175  ereport(ERROR,
3176  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
3177  errmsg("invalid multibyte character for locale"),
3178  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
3179  }
3180 
3181  return result;
3182 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
Assert(fmt[strlen(fmt) - 1] !='\n')
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1556
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1694
static size_t mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc)
Definition: pg_locale.c:166

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

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

◆ check_locale()

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

Definition at line 315 of file pg_locale.c.

316 {
317  char *save;
318  char *res;
319 
320  if (canonname)
321  *canonname = NULL; /* in case of failure */
322 
323  save = setlocale(category, NULL);
324  if (!save)
325  return false; /* won't happen, we hope */
326 
327  /* save may be pointing at a modifiable scratch variable, see above. */
328  save = pstrdup(save);
329 
330  /* set the locale with setlocale, to see if it accepts it. */
331  res = setlocale(category, locale);
332 
333  /* save canonical name if requested. */
334  if (res && canonname)
335  *canonname = pstrdup(res);
336 
337  /* restore old value. */
338  if (!setlocale(category, save))
339  elog(WARNING, "failed to restore old locale \"%s\"", save);
340  pfree(save);
341 
342  return (res != NULL);
343 }
#define WARNING
Definition: elog.h:36

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

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

◆ check_locale_messages()

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

Definition at line 404 of file pg_locale.c.

405 {
406  if (**newval == '\0')
407  {
408  if (source == PGC_S_DEFAULT)
409  return true;
410  else
411  return false;
412  }
413 
414  /*
415  * LC_MESSAGES category does not exist everywhere, but accept it anyway
416  *
417  * On Windows, we can't even check the value, so accept blindly
418  */
419 #if defined(LC_MESSAGES) && !defined(WIN32)
420  return check_locale(LC_MESSAGES, *newval, NULL);
421 #else
422  return true;
423 #endif
424 }
@ PGC_S_DEFAULT
Definition: guc.h:109
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:315
static rewind_source * source
Definition: pg_rewind.c:89

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

◆ check_locale_monetary()

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

Definition at line 358 of file pg_locale.c.

359 {
360  return check_locale(LC_MONETARY, *newval, NULL);
361 }

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 370 of file pg_locale.c.

371 {
372  return check_locale(LC_NUMERIC, *newval, NULL);
373 }

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 382 of file pg_locale.c.

383 {
384  return check_locale(LC_TIME, *newval, NULL);
385 }

References check_locale(), and newval.

◆ db_encoding_convert()

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

Definition at line 494 of file pg_locale.c.

495 {
496  char *pstr;
497  char *mstr;
498 
499  /* convert the string to the database encoding */
500  pstr = pg_any_to_server(*str, strlen(*str), encoding);
501  if (pstr == *str)
502  return; /* no conversion happened */
503 
504  /* need it malloc'd not palloc'd */
505  mstr = strdup(pstr);
506  if (mstr == NULL)
507  ereport(ERROR,
508  (errcode(ERRCODE_OUT_OF_MEMORY),
509  errmsg("out of memory")));
510 
511  /* replace old string */
512  free(*str);
513  *str = mstr;
514 
515  pfree(pstr);
516 }
#define free(a)
Definition: header.h:65

References encoding, ereport, errcode(), errmsg(), ERROR, free, pfree(), pg_any_to_server(), and generate_unaccent_rules::str.

Referenced by PGLC_localeconv().

◆ free_struct_lconv()

static void free_struct_lconv ( struct lconv *  s)
static

Definition at line 444 of file pg_locale.c.

445 {
446  free(s->decimal_point);
447  free(s->thousands_sep);
448  free(s->grouping);
449  free(s->int_curr_symbol);
450  free(s->currency_symbol);
451  free(s->mon_decimal_point);
452  free(s->mon_thousands_sep);
453  free(s->mon_grouping);
454  free(s->positive_sign);
455  free(s->negative_sign);
456 }

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1729 of file pg_locale.c.

1730 {
1731  char *collversion = NULL;
1732 
1733  /*
1734  * The only two supported locales (C and C.UTF-8) are both based on memcmp
1735  * and are not expected to change.
1736  *
1737  * Note that the character semantics may change for some locales, but the
1738  * collation version only tracks changes to sort order.
1739  */
1740  if (collprovider == COLLPROVIDER_BUILTIN)
1741  return NULL;
1742 
1743 #ifdef USE_ICU
1744  if (collprovider == COLLPROVIDER_ICU)
1745  {
1746  UCollator *collator;
1747  UVersionInfo versioninfo;
1748  char buf[U_MAX_VERSION_STRING_LENGTH];
1749 
1750  collator = pg_ucol_open(collcollate);
1751 
1752  ucol_getVersion(collator, versioninfo);
1753  ucol_close(collator);
1754 
1755  u_versionToString(versioninfo, buf);
1756  collversion = pstrdup(buf);
1757  }
1758  else
1759 #endif
1760  if (collprovider == COLLPROVIDER_LIBC &&
1761  pg_strcasecmp("C", collcollate) != 0 &&
1762  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1763  pg_strcasecmp("POSIX", collcollate) != 0)
1764  {
1765 #if defined(__GLIBC__)
1766  /* Use the glibc version because we don't have anything better. */
1767  collversion = pstrdup(gnu_get_libc_version());
1768 #elif defined(LC_VERSION_MASK)
1769  locale_t loc;
1770 
1771  /* Look up FreeBSD collation version. */
1772  loc = newlocale(LC_COLLATE, collcollate, NULL);
1773  if (loc)
1774  {
1775  collversion =
1776  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1777  freelocale(loc);
1778  }
1779  else
1780  ereport(ERROR,
1781  (errmsg("could not load locale \"%s\"", collcollate)));
1782 #elif defined(WIN32)
1783  /*
1784  * If we are targeting Windows Vista and above, we can ask for a name
1785  * given a collation name (earlier versions required a location code
1786  * that we don't have).
1787  */
1788  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1789  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1790 
1791  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1792  LOCALE_NAME_MAX_LENGTH);
1793  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1794  {
1795  /*
1796  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1797  * locale name like "English_United States.1252". Until those
1798  * values can be prevented from entering the system, or 100%
1799  * reliably converted to the more useful tag format, tolerate the
1800  * resulting error and report that we have no version data.
1801  */
1802  if (GetLastError() == ERROR_INVALID_PARAMETER)
1803  return NULL;
1804 
1805  ereport(ERROR,
1806  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1807  collcollate,
1808  GetLastError())));
1809  }
1810  collversion = psprintf("%lu.%lu,%lu.%lu",
1811  (version.dwNLSVersion >> 8) & 0xFFFF,
1812  version.dwNLSVersion & 0xFF,
1813  (version.dwDefinedVersion >> 8) & 0xFFFF,
1814  version.dwDefinedVersion & 0xFF);
1815 #endif
1816  }
1817 
1818  return collversion;
1819 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define locale_t
Definition: win32_port.h:424

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

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

◆ icu_language_tag()

char* icu_language_tag ( const char *  loc_str,
int  elevel 
)

Definition at line 2917 of file pg_locale.c.

2918 {
2919 #ifdef USE_ICU
2920  UErrorCode status;
2921  char *langtag;
2922  size_t buflen = 32; /* arbitrary starting buffer size */
2923  const bool strict = true;
2924 
2925  /*
2926  * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
2927  * RFC5646 section 4.4). Additionally, in older ICU versions,
2928  * uloc_toLanguageTag() doesn't always return the ultimate length on the
2929  * first call, necessitating a loop.
2930  */
2931  langtag = palloc(buflen);
2932  while (true)
2933  {
2934  status = U_ZERO_ERROR;
2935  uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
2936 
2937  /* try again if the buffer is not large enough */
2938  if ((status == U_BUFFER_OVERFLOW_ERROR ||
2939  status == U_STRING_NOT_TERMINATED_WARNING) &&
2940  buflen < MaxAllocSize)
2941  {
2942  buflen = Min(buflen * 2, MaxAllocSize);
2943  langtag = repalloc(langtag, buflen);
2944  continue;
2945  }
2946 
2947  break;
2948  }
2949 
2950  if (U_FAILURE(status))
2951  {
2952  pfree(langtag);
2953 
2954  if (elevel > 0)
2955  ereport(elevel,
2956  (errmsg("could not convert locale name \"%s\" to language tag: %s",
2957  loc_str, u_errorName(status))));
2958  return NULL;
2959  }
2960 
2961  return langtag;
2962 #else /* not USE_ICU */
2963  ereport(ERROR,
2964  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2965  errmsg("ICU is not supported in this build")));
2966  return NULL; /* keep compiler quiet */
2967 #endif /* not USE_ICU */
2968 }
#define Min(x, y)
Definition: c.h:991
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1528
void * palloc(Size size)
Definition: mcxt.c:1304
#define MaxAllocSize
Definition: memutils.h:40

References ereport, errcode(), errmsg(), ERROR, MaxAllocSize, Min, palloc(), pfree(), and repalloc().

Referenced by createdb(), DefineCollation(), and pg_import_system_collations().

◆ icu_validate_locale()

void icu_validate_locale ( const char *  loc_str)

Definition at line 2974 of file pg_locale.c.

2975 {
2976 #ifdef USE_ICU
2977  UCollator *collator;
2978  UErrorCode status;
2979  char lang[ULOC_LANG_CAPACITY];
2980  bool found = false;
2981  int elevel = icu_validation_level;
2982 
2983  /* no validation */
2984  if (elevel < 0)
2985  return;
2986 
2987  /* downgrade to WARNING during pg_upgrade */
2988  if (IsBinaryUpgrade && elevel > WARNING)
2989  elevel = WARNING;
2990 
2991  /* validate that we can extract the language */
2992  status = U_ZERO_ERROR;
2993  uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
2994  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2995  {
2996  ereport(elevel,
2997  (errmsg("could not get language from ICU locale \"%s\": %s",
2998  loc_str, u_errorName(status)),
2999  errhint("To disable ICU locale validation, set the parameter %s to \"%s\".",
3000  "icu_validation_level", "disabled")));
3001  return;
3002  }
3003 
3004  /* check for special language name */
3005  if (strcmp(lang, "") == 0 ||
3006  strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
3007  found = true;
3008 
3009  /* search for matching language within ICU */
3010  for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
3011  {
3012  const char *otherloc = uloc_getAvailable(i);
3013  char otherlang[ULOC_LANG_CAPACITY];
3014 
3015  status = U_ZERO_ERROR;
3016  uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
3017  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
3018  continue;
3019 
3020  if (strcmp(lang, otherlang) == 0)
3021  found = true;
3022  }
3023 
3024  if (!found)
3025  ereport(elevel,
3026  (errmsg("ICU locale \"%s\" has unknown language \"%s\"",
3027  loc_str, lang),
3028  errhint("To disable ICU locale validation, set the parameter %s to \"%s\".",
3029  "icu_validation_level", "disabled")));
3030 
3031  /* check that it can be opened */
3032  collator = pg_ucol_open(loc_str);
3033  ucol_close(collator);
3034 #else /* not USE_ICU */
3035  /* could get here if a collation was created by a build with ICU */
3036  ereport(ERROR,
3037  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3038  errmsg("ICU is not supported in this build")));
3039 #endif /* not USE_ICU */
3040 }
bool IsBinaryUpgrade
Definition: globals.c:118
int icu_validation_level
Definition: pg_locale.c:102

References ereport, errcode(), errhint(), errmsg(), ERROR, i, icu_validation_level, IsBinaryUpgrade, and WARNING.

Referenced by createdb(), and DefineCollation().

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1317 of file pg_locale.c.

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

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

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

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1384 of file pg_locale.c.

1385 {
1386  /*
1387  * If we're asked about "collation 0", return false, so that the code will
1388  * go into the non-C path and report that the collation is bogus.
1389  */
1390  if (!OidIsValid(collation))
1391  return false;
1392 
1393  /*
1394  * If we're asked about the default collation, we have to inquire of the C
1395  * library. Cache the result so we only have to compute it once.
1396  */
1397  if (collation == DEFAULT_COLLATION_OID)
1398  {
1399  static int result = -1;
1400  const char *localeptr;
1401 
1402  if (result >= 0)
1403  return (bool) result;
1404 
1405  if (default_locale.provider == COLLPROVIDER_BUILTIN)
1406  {
1407  localeptr = default_locale.info.builtin.locale;
1408  }
1409  else if (default_locale.provider == COLLPROVIDER_ICU)
1410  {
1411  result = false;
1412  return (bool) result;
1413  }
1414  else if (default_locale.provider == COLLPROVIDER_LIBC)
1415  {
1416  localeptr = setlocale(LC_CTYPE, NULL);
1417  if (!localeptr)
1418  elog(ERROR, "invalid LC_CTYPE setting");
1419  }
1420  else
1421  elog(ERROR, "unexpected collation provider '%c'",
1423 
1424  if (strcmp(localeptr, "C") == 0)
1425  result = true;
1426  else if (strcmp(localeptr, "POSIX") == 0)
1427  result = true;
1428  else
1429  result = false;
1430  return (bool) result;
1431  }
1432 
1433  /*
1434  * If we're asked about the built-in C/POSIX collations, we know that.
1435  */
1436  if (collation == C_COLLATION_OID ||
1437  collation == POSIX_COLLATION_OID)
1438  return true;
1439 
1440  /*
1441  * Otherwise, we have to consult pg_collation, but we cache that.
1442  */
1443  return (lookup_collation_cache(collation, true))->ctype_is_c;
1444 }
struct pg_locale_struct::@150::@151 builtin
union pg_locale_struct::@150 info

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

◆ lookup_collation_cache()

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

Definition at line 1230 of file pg_locale.c.

1231 {
1232  collation_cache_entry *cache_entry;
1233  bool found;
1234 
1235  Assert(OidIsValid(collation));
1236  Assert(collation != DEFAULT_COLLATION_OID);
1237 
1238  if (collation_cache == NULL)
1239  {
1240  /* First time through, initialize the hash table */
1241  HASHCTL ctl;
1242 
1243  ctl.keysize = sizeof(Oid);
1244  ctl.entrysize = sizeof(collation_cache_entry);
1245  collation_cache = hash_create("Collation cache", 100, &ctl,
1246  HASH_ELEM | HASH_BLOBS);
1247  }
1248 
1249  cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
1250  if (!found)
1251  {
1252  /*
1253  * Make sure cache entry is marked invalid, in case we fail before
1254  * setting things.
1255  */
1256  cache_entry->flags_valid = false;
1257  cache_entry->locale = 0;
1258  }
1259 
1260  if (set_flags && !cache_entry->flags_valid)
1261  {
1262  /* Attempt to set the flags */
1263  HeapTuple tp;
1264  Form_pg_collation collform;
1265 
1266  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1267  if (!HeapTupleIsValid(tp))
1268  elog(ERROR, "cache lookup failed for collation %u", collation);
1269  collform = (Form_pg_collation) GETSTRUCT(tp);
1270 
1271  if (collform->collprovider == COLLPROVIDER_BUILTIN)
1272  {
1273  Datum datum;
1274  const char *colllocale;
1275 
1276  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1277  colllocale = TextDatumGetCString(datum);
1278 
1279  cache_entry->collate_is_c = true;
1280  cache_entry->ctype_is_c = (strcmp(colllocale, "C") == 0);
1281  }
1282  else if (collform->collprovider == COLLPROVIDER_LIBC)
1283  {
1284  Datum datum;
1285  const char *collcollate;
1286  const char *collctype;
1287 
1288  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1289  collcollate = TextDatumGetCString(datum);
1290  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1291  collctype = TextDatumGetCString(datum);
1292 
1293  cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) ||
1294  (strcmp(collcollate, "POSIX") == 0));
1295  cache_entry->ctype_is_c = ((strcmp(collctype, "C") == 0) ||
1296  (strcmp(collctype, "POSIX") == 0));
1297  }
1298  else
1299  {
1300  cache_entry->collate_is_c = false;
1301  cache_entry->ctype_is_c = false;
1302  }
1303 
1304  cache_entry->flags_valid = true;
1305 
1306  ReleaseSysCache(tp);
1307  }
1308 
1309  return cache_entry;
1310 }
#define TextDatumGetCString(d)
Definition: builtins.h:98
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
static HTAB * collation_cache
Definition: pg_locale.c:134
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
tree ctl
Definition: radixtree.h:1807
Definition: pg_locale.c:126
bool collate_is_c
Definition: pg_locale.c:128
pg_locale_t locale
Definition: pg_locale.c:131
bool flags_valid
Definition: pg_locale.c:130
bool ctype_is_c
Definition: pg_locale.c:129
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510

References Assert(), collation_cache_entry::collate_is_c, collation_cache, ctl, collation_cache_entry::ctype_is_c, elog, ERROR, collation_cache_entry::flags_valid, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, collation_cache_entry::locale, ObjectIdGetDatum(), OidIsValid, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

Referenced by lc_collate_is_c(), and pg_newlocale_from_collation().

◆ make_icu_collator()

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

Definition at line 1449 of file pg_locale.c.

1452 {
1453 #ifdef USE_ICU
1454  UCollator *collator;
1455 
1456  collator = pg_ucol_open(iculocstr);
1457 
1458  /*
1459  * If rules are specified, we extract the rules of the standard collation,
1460  * add our own rules, and make a new collator with the combined rules.
1461  */
1462  if (icurules)
1463  {
1464  const UChar *default_rules;
1465  UChar *agg_rules;
1466  UChar *my_rules;
1467  UErrorCode status;
1468  int32_t length;
1469 
1470  default_rules = ucol_getRules(collator, &length);
1471  icu_to_uchar(&my_rules, icurules, strlen(icurules));
1472 
1473  agg_rules = palloc_array(UChar, u_strlen(default_rules) + u_strlen(my_rules) + 1);
1474  u_strcpy(agg_rules, default_rules);
1475  u_strcat(agg_rules, my_rules);
1476 
1477  ucol_close(collator);
1478 
1479  status = U_ZERO_ERROR;
1480  collator = ucol_openRules(agg_rules, u_strlen(agg_rules),
1481  UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
1482  if (U_FAILURE(status))
1483  ereport(ERROR,
1484  (errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s",
1485  iculocstr, icurules, u_errorName(status))));
1486  }
1487 
1488  /* We will leak this string if the caller errors later :-( */
1489  resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1490  resultp->info.icu.ucol = collator;
1491 #else /* not USE_ICU */
1492  /* could get here if a collation was created by a build with ICU */
1493  ereport(ERROR,
1494  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1495  errmsg("ICU is not supported in this build")));
1496 #endif /* not USE_ICU */
1497 }
#define palloc_array(type, count)
Definition: fe_memutils.h:64
const char * locale
Definition: pg_locale.h:81

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

Referenced by CheckMyDatabase(), and pg_newlocale_from_collation().

◆ mbstowcs_l()

static size_t mbstowcs_l ( wchar_t *  dest,
const char *  src,
size_t  n,
locale_t  loc 
)
static

Definition at line 166 of file pg_locale.c.

167 {
168 #ifdef WIN32
169  return _mbstowcs_l(dest, src, n, loc);
170 #else
171  size_t result;
172  locale_t save_locale = uselocale(loc);
173 
174  result = mbstowcs(dest, src, n);
175  uselocale(save_locale);
176  return result;
177 #endif
178 }

References generate_unaccent_rules::dest, and locale_t.

Referenced by char2wchar().

◆ pg_locale_deterministic()

bool pg_locale_deterministic ( pg_locale_t  locale)

Definition at line 1531 of file pg_locale.c.

1532 {
1533  /* default locale must always be deterministic */
1534  if (locale == NULL)
1535  return true;
1536  else
1537  return locale->deterministic;
1538 }

References locale.

Referenced by bpchareq(), bpcharne(), Generic_Text_IC_like(), GenericMatchText(), hashbpchar(), hashbpcharextended(), hashtext(), hashtextextended(), pg_set_regex_collation(), text_position_setup(), text_starts_with(), texteq(), textne(), varstr_cmp(), and varstrfastcmp_locale().

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1551 of file pg_locale.c.

1552 {
1553  collation_cache_entry *cache_entry;
1554 
1555  /* Callers must pass a valid OID */
1557 
1558  if (collid == DEFAULT_COLLATION_OID)
1559  {
1560  if (default_locale.provider == COLLPROVIDER_LIBC)
1561  return (pg_locale_t) 0;
1562  else
1563  return &default_locale;
1564  }
1565 
1566  cache_entry = lookup_collation_cache(collid, false);
1567 
1568  if (cache_entry->locale == 0)
1569  {
1570  /* We haven't computed this yet in this session, so do it */
1571  HeapTuple tp;
1572  Form_pg_collation collform;
1573  struct pg_locale_struct result;
1574  pg_locale_t resultp;
1575  Datum datum;
1576  bool isnull;
1577 
1578  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1579  if (!HeapTupleIsValid(tp))
1580  elog(ERROR, "cache lookup failed for collation %u", collid);
1581  collform = (Form_pg_collation) GETSTRUCT(tp);
1582 
1583  /* We'll fill in the result struct locally before allocating memory */
1584  memset(&result, 0, sizeof(result));
1585  result.provider = collform->collprovider;
1586  result.deterministic = collform->collisdeterministic;
1587 
1588  if (collform->collprovider == COLLPROVIDER_BUILTIN)
1589  {
1590  const char *locstr;
1591 
1592  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1593  locstr = TextDatumGetCString(datum);
1594 
1596 
1597  result.info.builtin.locale = MemoryContextStrdup(TopMemoryContext,
1598  locstr);
1599  }
1600  else if (collform->collprovider == COLLPROVIDER_LIBC)
1601  {
1602  const char *collcollate;
1603  const char *collctype pg_attribute_unused();
1604  locale_t loc;
1605 
1606  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1607  collcollate = TextDatumGetCString(datum);
1608  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1609  collctype = TextDatumGetCString(datum);
1610 
1611  if (strcmp(collcollate, collctype) == 0)
1612  {
1613  /* Normal case where they're the same */
1614  errno = 0;
1615 #ifndef WIN32
1616  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1617  NULL);
1618 #else
1619  loc = _create_locale(LC_ALL, collcollate);
1620 #endif
1621  if (!loc)
1622  report_newlocale_failure(collcollate);
1623  }
1624  else
1625  {
1626 #ifndef WIN32
1627  /* We need two newlocale() steps */
1628  locale_t loc1;
1629 
1630  errno = 0;
1631  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1632  if (!loc1)
1633  report_newlocale_failure(collcollate);
1634  errno = 0;
1635  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1636  if (!loc)
1637  report_newlocale_failure(collctype);
1638 #else
1639 
1640  /*
1641  * XXX The _create_locale() API doesn't appear to support
1642  * this. Could perhaps be worked around by changing
1643  * pg_locale_t to contain two separate fields.
1644  */
1645  ereport(ERROR,
1646  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1647  errmsg("collations with different collate and ctype values are not supported on this platform")));
1648 #endif
1649  }
1650 
1651  result.info.lt = loc;
1652  }
1653  else if (collform->collprovider == COLLPROVIDER_ICU)
1654  {
1655  const char *iculocstr;
1656  const char *icurules;
1657 
1658  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1659  iculocstr = TextDatumGetCString(datum);
1660 
1661  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1662  if (!isnull)
1663  icurules = TextDatumGetCString(datum);
1664  else
1665  icurules = NULL;
1666 
1667  make_icu_collator(iculocstr, icurules, &result);
1668  }
1669 
1670  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1671  &isnull);
1672  if (!isnull)
1673  {
1674  char *actual_versionstr;
1675  char *collversionstr;
1676 
1677  collversionstr = TextDatumGetCString(datum);
1678 
1679  if (collform->collprovider == COLLPROVIDER_LIBC)
1680  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1681  else
1682  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1683 
1684  actual_versionstr = get_collation_actual_version(collform->collprovider,
1685  TextDatumGetCString(datum));
1686  if (!actual_versionstr)
1687  {
1688  /*
1689  * This could happen when specifying a version in CREATE
1690  * COLLATION but the provider does not support versioning, or
1691  * manually creating a mess in the catalogs.
1692  */
1693  ereport(ERROR,
1694  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1695  NameStr(collform->collname))));
1696  }
1697 
1698  if (strcmp(actual_versionstr, collversionstr) != 0)
1699  ereport(WARNING,
1700  (errmsg("collation \"%s\" has version mismatch",
1701  NameStr(collform->collname)),
1702  errdetail("The collation in the database was created using version %s, "
1703  "but the operating system provides version %s.",
1704  collversionstr, actual_versionstr),
1705  errhint("Rebuild all objects affected by this collation and run "
1706  "ALTER COLLATION %s REFRESH VERSION, "
1707  "or build PostgreSQL with the right library version.",
1708  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1709  NameStr(collform->collname)))));
1710  }
1711 
1712  ReleaseSysCache(tp);
1713 
1714  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1715  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1716  *resultp = result;
1717 
1718  cache_entry->locale = resultp;
1719  }
1720 
1721  return cache_entry->locale;
1722 }
#define NameStr(name)
Definition: c.h:733
#define pg_attribute_unused()
Definition: c.h:123
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1205
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3344
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1168
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1449
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1729
static void report_newlocale_failure(const char *localename)
Definition: pg_locale.c:1502
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:2541
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12437
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479

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

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

◆ pg_perm_setlocale()

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

Definition at line 212 of file pg_locale.c.

213 {
214  char *result;
215  const char *envvar;
216 
217 #ifndef WIN32
218  result = setlocale(category, locale);
219 #else
220 
221  /*
222  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
223  * the given value is good and set it in the environment variables. We
224  * must ignore attempts to set to "", which means "keep using the old
225  * environment value".
226  */
227 #ifdef LC_MESSAGES
228  if (category == LC_MESSAGES)
229  {
230  result = (char *) locale;
231  if (locale == NULL || locale[0] == '\0')
232  return result;
233  }
234  else
235 #endif
236  result = setlocale(category, locale);
237 #endif /* WIN32 */
238 
239  if (result == NULL)
240  return result; /* fall out immediately on failure */
241 
242  /*
243  * Use the right encoding in translated messages. Under ENABLE_NLS, let
244  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
245  * format strings are ASCII, but database-encoding strings may enter the
246  * message via %s. This makes the overall message encoding equal to the
247  * database encoding.
248  */
249  if (category == LC_CTYPE)
250  {
251  static char save_lc_ctype[LOCALE_NAME_BUFLEN];
252 
253  /* copy setlocale() return value before callee invokes it again */
254  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
255  result = save_lc_ctype;
256 
257 #ifdef ENABLE_NLS
258  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
259 #else
261 #endif
262  }
263 
264  switch (category)
265  {
266  case LC_COLLATE:
267  envvar = "LC_COLLATE";
268  break;
269  case LC_CTYPE:
270  envvar = "LC_CTYPE";
271  break;
272 #ifdef LC_MESSAGES
273  case LC_MESSAGES:
274  envvar = "LC_MESSAGES";
275 #ifdef WIN32
276  result = IsoLocaleName(locale);
277  if (result == NULL)
278  result = (char *) locale;
279  elog(DEBUG3, "IsoLocaleName() executed; locale: \"%s\"", result);
280 #endif /* WIN32 */
281  break;
282 #endif /* LC_MESSAGES */
283  case LC_MONETARY:
284  envvar = "LC_MONETARY";
285  break;
286  case LC_NUMERIC:
287  envvar = "LC_NUMERIC";
288  break;
289  case LC_TIME:
290  envvar = "LC_TIME";
291  break;
292  default:
293  elog(FATAL, "unrecognized LC category: %d", category);
294  return NULL; /* keep compiler quiet */
295  }
296 
297  if (setenv(envvar, result, 1) != 0)
298  return NULL;
299 
300  return result;
301 }
void SetMessageEncoding(int encoding)
Definition: mbutils.c:1171
#define LOCALE_NAME_BUFLEN
Definition: pg_locale.h:36
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define setenv(x, y, z)
Definition: win32_port.h:537

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

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

◆ pg_strcoll()

int pg_strcoll ( const char *  arg1,
const char *  arg2,
pg_locale_t  locale 
)

Definition at line 2088 of file pg_locale.c.

2089 {
2090  int result;
2091 
2092  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2093  result = pg_strcoll_libc(arg1, arg2, locale);
2094 #ifdef USE_ICU
2095  else if (locale->provider == COLLPROVIDER_ICU)
2096  result = pg_strncoll_icu(arg1, -1, arg2, -1, locale);
2097 #endif
2098  else
2099  /* shouldn't happen */
2100  PGLOCALE_SUPPORT_ERROR(locale->provider);
2101 
2102  return result;
2103 }
#define PGLOCALE_SUPPORT_ERROR(provider)
Definition: pg_locale.c:84
static int pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale)
Definition: pg_locale.c:1906

References locale, pg_strcoll_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by varstrfastcmp_locale().

◆ pg_strcoll_libc()

static int pg_strcoll_libc ( const char *  arg1,
const char *  arg2,
pg_locale_t  locale 
)
static

Definition at line 1906 of file pg_locale.c.

1907 {
1908  int result;
1909 
1910  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1911 #ifdef WIN32
1912  if (GetDatabaseEncoding() == PG_UTF8)
1913  {
1914  size_t len1 = strlen(arg1);
1915  size_t len2 = strlen(arg2);
1916 
1917  result = pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1918  }
1919  else
1920 #endif /* WIN32 */
1921  if (locale)
1922  result = strcoll_l(arg1, arg2, locale->info.lt);
1923  else
1924  result = strcoll(arg1, arg2);
1925 
1926  return result;
1927 }
#define strcoll_l
Definition: win32_port.h:447

References Assert(), GetDatabaseEncoding(), locale, PG_UTF8, and strcoll_l.

Referenced by pg_strcoll(), and pg_strncoll_libc().

◆ pg_strncoll()

int pg_strncoll ( const char *  arg1,
size_t  len1,
const char *  arg2,
size_t  len2,
pg_locale_t  locale 
)

Definition at line 2123 of file pg_locale.c.

2125 {
2126  int result;
2127 
2128  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2129  result = pg_strncoll_libc(arg1, len1, arg2, len2, locale);
2130 #ifdef USE_ICU
2131  else if (locale->provider == COLLPROVIDER_ICU)
2132  result = pg_strncoll_icu(arg1, len1, arg2, len2, locale);
2133 #endif
2134  else
2135  /* shouldn't happen */
2136  PGLOCALE_SUPPORT_ERROR(locale->provider);
2137 
2138  return result;
2139 }
static int pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
Definition: pg_locale.c:1935

References locale, pg_strncoll_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_cmp().

◆ pg_strncoll_libc()

static int pg_strncoll_libc ( const char *  arg1,
size_t  len1,
const char *  arg2,
size_t  len2,
pg_locale_t  locale 
)
static

Definition at line 1935 of file pg_locale.c.

1937 {
1938  char sbuf[TEXTBUFLEN];
1939  char *buf = sbuf;
1940  size_t bufsize1 = len1 + 1;
1941  size_t bufsize2 = len2 + 1;
1942  char *arg1n;
1943  char *arg2n;
1944  int result;
1945 
1946  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1947 
1948 #ifdef WIN32
1949  /* check for this case before doing the work for nul-termination */
1950  if (GetDatabaseEncoding() == PG_UTF8)
1951  return pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1952 #endif /* WIN32 */
1953 
1954  if (bufsize1 + bufsize2 > TEXTBUFLEN)
1955  buf = palloc(bufsize1 + bufsize2);
1956 
1957  arg1n = buf;
1958  arg2n = buf + bufsize1;
1959 
1960  /* nul-terminate arguments */
1961  memcpy(arg1n, arg1, len1);
1962  arg1n[len1] = '\0';
1963  memcpy(arg2n, arg2, len2);
1964  arg2n[len2] = '\0';
1965 
1966  result = pg_strcoll_libc(arg1n, arg2n, locale);
1967 
1968  if (buf != sbuf)
1969  pfree(buf);
1970 
1971  return result;
1972 }
#define TEXTBUFLEN
Definition: pg_locale.c:91

References Assert(), buf, GetDatabaseEncoding(), locale, palloc(), pfree(), pg_strcoll_libc(), PG_UTF8, and TEXTBUFLEN.

Referenced by pg_strncoll().

◆ pg_strnxfrm()

size_t pg_strnxfrm ( char *  dest,
size_t  destsize,
const char *  src,
size_t  srclen,
pg_locale_t  locale 
)

Definition at line 2407 of file pg_locale.c.

2409 {
2410  size_t result = 0; /* keep compiler quiet */
2411 
2412  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2413  result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale);
2414 #ifdef USE_ICU
2415  else if (locale->provider == COLLPROVIDER_ICU)
2416  result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale);
2417 #endif
2418  else
2419  /* shouldn't happen */
2420  PGLOCALE_SUPPORT_ERROR(locale->provider);
2421 
2422  return result;
2423 }
static size_t pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2161

References generate_unaccent_rules::dest, locale, pg_strnxfrm_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by hashbpchar(), hashbpcharextended(), hashtext(), and hashtextextended().

◆ pg_strnxfrm_libc()

static size_t pg_strnxfrm_libc ( char *  dest,
const char *  src,
size_t  srclen,
size_t  destsize,
pg_locale_t  locale 
)
static

Definition at line 2161 of file pg_locale.c.

2163 {
2164  char sbuf[TEXTBUFLEN];
2165  char *buf = sbuf;
2166  size_t bufsize = srclen + 1;
2167  size_t result;
2168 
2169  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2170 
2171  if (bufsize > TEXTBUFLEN)
2172  buf = palloc(bufsize);
2173 
2174  /* nul-terminate arguments */
2175  memcpy(buf, src, srclen);
2176  buf[srclen] = '\0';
2177 
2178  result = pg_strxfrm_libc(dest, buf, destsize, locale);
2179 
2180  if (buf != sbuf)
2181  pfree(buf);
2182 
2183  /* if dest is defined, it should be nul-terminated */
2184  Assert(result >= destsize || dest[result] == '\0');
2185 
2186  return result;
2187 }
#define bufsize
Definition: indent_globs.h:36
static size_t pg_strxfrm_libc(char *dest, const char *src, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2143

References Assert(), buf, bufsize, generate_unaccent_rules::dest, locale, palloc(), pfree(), pg_strxfrm_libc(), and TEXTBUFLEN.

Referenced by pg_strnxfrm().

◆ pg_strnxfrm_prefix()

size_t pg_strnxfrm_prefix ( char *  dest,
size_t  destsize,
const char *  src,
size_t  srclen,
pg_locale_t  locale 
)

Definition at line 2492 of file pg_locale.c.

2494 {
2495  size_t result = 0; /* keep compiler quiet */
2496 
2497  if (!locale)
2498  PGLOCALE_SUPPORT_ERROR(COLLPROVIDER_LIBC);
2499 #ifdef USE_ICU
2500  else if (locale->provider == COLLPROVIDER_ICU)
2501  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2502 #endif
2503  else
2504  PGLOCALE_SUPPORT_ERROR(locale->provider);
2505 
2506  return result;
2507 }

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

◆ pg_strxfrm()

size_t pg_strxfrm ( char *  dest,
const char *  src,
size_t  destsize,
pg_locale_t  locale 
)

Definition at line 2371 of file pg_locale.c.

2372 {
2373  size_t result = 0; /* keep compiler quiet */
2374 
2375  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2376  result = pg_strxfrm_libc(dest, src, destsize, locale);
2377 #ifdef USE_ICU
2378  else if (locale->provider == COLLPROVIDER_ICU)
2379  result = pg_strnxfrm_icu(dest, src, -1, destsize, locale);
2380 #endif
2381  else
2382  /* shouldn't happen */
2383  PGLOCALE_SUPPORT_ERROR(locale->provider);
2384 
2385  return result;
2386 }

References generate_unaccent_rules::dest, locale, pg_strxfrm_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 2339 of file pg_locale.c.

2340 {
2341  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2342 #ifdef TRUST_STRXFRM
2343  return true;
2344 #else
2345  return false;
2346 #endif
2347  else if (locale->provider == COLLPROVIDER_ICU)
2348  return true;
2349  else
2350  /* shouldn't happen */
2351  PGLOCALE_SUPPORT_ERROR(locale->provider);
2352 
2353  return false; /* keep compiler quiet */
2354 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_sortsupport().

◆ pg_strxfrm_libc()

static size_t pg_strxfrm_libc ( char *  dest,
const char *  src,
size_t  destsize,
pg_locale_t  locale 
)
static

Definition at line 2143 of file pg_locale.c.

2145 {
2146  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2147 
2148 #ifdef TRUST_STRXFRM
2149  if (locale)
2150  return strxfrm_l(dest, src, destsize, locale->info.lt);
2151  else
2152  return strxfrm(dest, src, destsize);
2153 #else
2154  /* shouldn't happen */
2155  PGLOCALE_SUPPORT_ERROR(locale->provider);
2156  return 0; /* keep compiler quiet */
2157 #endif
2158 }
#define strxfrm_l
Definition: win32_port.h:448

References Assert(), generate_unaccent_rules::dest, locale, PGLOCALE_SUPPORT_ERROR, and strxfrm_l.

Referenced by pg_strnxfrm_libc(), and pg_strxfrm().

◆ pg_strxfrm_prefix()

size_t pg_strxfrm_prefix ( char *  dest,
const char *  src,
size_t  destsize,
pg_locale_t  locale 
)

Definition at line 2457 of file pg_locale.c.

2459 {
2460  size_t result = 0; /* keep compiler quiet */
2461 
2462  if (!locale)
2463  PGLOCALE_SUPPORT_ERROR(COLLPROVIDER_LIBC);
2464 #ifdef USE_ICU
2465  else if (locale->provider == COLLPROVIDER_ICU)
2466  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2467 #endif
2468  else
2469  PGLOCALE_SUPPORT_ERROR(locale->provider);
2470 
2471  return result;
2472 }

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_prefix_enabled()

bool pg_strxfrm_prefix_enabled ( pg_locale_t  locale)

Definition at line 2430 of file pg_locale.c.

2431 {
2432  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2433  return false;
2434  else if (locale->provider == COLLPROVIDER_ICU)
2435  return true;
2436  else
2437  /* shouldn't happen */
2438  PGLOCALE_SUPPORT_ERROR(locale->provider);
2439 
2440  return false; /* keep compiler quiet */
2441 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 524 of file pg_locale.c.

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

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

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

◆ report_newlocale_failure()

static void report_newlocale_failure ( const char *  localename)
static

Definition at line 1502 of file pg_locale.c.

1503 {
1504  int save_errno;
1505 
1506  /*
1507  * Windows doesn't provide any useful error indication from
1508  * _create_locale(), and BSD-derived platforms don't seem to feel they
1509  * need to set errno either (even though POSIX is pretty clear that
1510  * newlocale should do so). So, if errno hasn't been set, assume ENOENT
1511  * is what to report.
1512  */
1513  if (errno == 0)
1514  errno = ENOENT;
1515 
1516  /*
1517  * ENOENT means "no such locale", not "no such file", so clarify that
1518  * errno with an errdetail message.
1519  */
1520  save_errno = errno; /* auxiliary funcs might change errno */
1521  ereport(ERROR,
1522  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1523  errmsg("could not create locale \"%s\": %m",
1524  localename),
1525  (save_errno == ENOENT ?
1526  errdetail("The operating system could not find any locale data for the locale name \"%s\".",
1527  localename) : 0)));
1528 }

References ereport, errcode(), errdetail(), errmsg(), and ERROR.

Referenced by pg_newlocale_from_collation().

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 463 of file pg_locale.c.

464 {
465  if (s->decimal_point == NULL)
466  return false;
467  if (s->thousands_sep == NULL)
468  return false;
469  if (s->grouping == NULL)
470  return false;
471  if (s->int_curr_symbol == NULL)
472  return false;
473  if (s->currency_symbol == NULL)
474  return false;
475  if (s->mon_decimal_point == NULL)
476  return false;
477  if (s->mon_thousands_sep == NULL)
478  return false;
479  if (s->mon_grouping == NULL)
480  return false;
481  if (s->positive_sign == NULL)
482  return false;
483  if (s->negative_sign == NULL)
484  return false;
485  return true;
486 }

Referenced by PGLC_localeconv().

◆ wchar2char()

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

Definition at line 3055 of file pg_locale.c.

3056 {
3057  size_t result;
3058 
3059  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
3060 
3061  if (tolen == 0)
3062  return 0;
3063 
3064 #ifdef WIN32
3065 
3066  /*
3067  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
3068  * for some reason mbstowcs and wcstombs won't do this for us, so we use
3069  * MultiByteToWideChar().
3070  */
3071  if (GetDatabaseEncoding() == PG_UTF8)
3072  {
3073  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
3074  NULL, NULL);
3075  /* A zero return is failure */
3076  if (result <= 0)
3077  result = -1;
3078  else
3079  {
3080  Assert(result <= tolen);
3081  /* Microsoft counts the zero terminator in the result */
3082  result--;
3083  }
3084  }
3085  else
3086 #endif /* WIN32 */
3087  if (locale == (pg_locale_t) 0)
3088  {
3089  /* Use wcstombs directly for the default locale */
3090  result = wcstombs(to, from, tolen);
3091  }
3092  else
3093  {
3094  /* Use wcstombs_l for nondefault locales */
3095  result = wcstombs_l(to, from, tolen, locale->info.lt);
3096  }
3097 
3098  return result;
3099 }
static size_t wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc)
Definition: pg_locale.c:182

References Assert(), GetDatabaseEncoding(), locale, PG_UTF8, and wcstombs_l().

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

◆ wcstombs_l()

static size_t wcstombs_l ( char *  dest,
const wchar_t *  src,
size_t  n,
locale_t  loc 
)
static

Definition at line 182 of file pg_locale.c.

183 {
184 #ifdef WIN32
185  return _wcstombs_l(dest, src, n, loc);
186 #else
187  size_t result;
188  locale_t save_locale = uselocale(loc);
189 
190  result = wcstombs(dest, src, n);
191  uselocale(save_locale);
192  return result;
193 #endif
194 }

References generate_unaccent_rules::dest, and locale_t.

Referenced by wchar2char().

Variable Documentation

◆ collation_cache

HTAB* collation_cache = NULL
static

Definition at line 134 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 121 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 120 of file pg_locale.c.

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

◆ database_ctype_is_c

bool database_ctype_is_c = false

◆ default_locale

struct pg_locale_struct default_locale

Definition at line 1384 of file pg_locale.c.

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

◆ icu_validation_level

int icu_validation_level = WARNING

Definition at line 102 of file pg_locale.c.

Referenced by createdb(), DefineCollation(), and icu_validate_locale().

◆ locale_messages

char* locale_messages

Definition at line 97 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 98 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 99 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 100 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 111 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 113 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 112 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 114 of file pg_locale.c.

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