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_database.h"
#include "common/hashfn.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/guc_hooks.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/syscache.h"
#include "lib/simplehash.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
 
#define SH_PREFIX   collation_cache
 
#define SH_ELEMENT_TYPE   collation_cache_entry
 
#define SH_KEY_TYPE   Oid
 
#define SH_KEY   collid
 
#define SH_HASH_KEY(tb, key)   murmurhash32((uint32) key)
 
#define SH_EQUAL(tb, a, b)   (a == b)
 
#define SH_GET_HASH(tb, a)   a->hash
 
#define SH_SCOPE   static inline
 
#define SH_STORE_HASH
 
#define SH_DECLARE
 
#define SH_DEFINE
 

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)
 
static void report_newlocale_failure (const char *localename)
 
static void make_libc_collator (const char *collate, const char *ctype, pg_locale_t result)
 
void make_icu_collator (const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
 
void init_database_collation (void)
 
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 struct pg_locale_struct default_locale
 
static bool CurrentLocaleConvValid = false
 
static bool CurrentLCTimeValid = false
 
static MemoryContext CollationCacheContext = NULL
 
static collation_cache_hash * CollationCache = NULL
 
static Oid last_collation_cache_oid = InvalidOid
 
static pg_locale_t last_collation_cache_locale = NULL
 

Macro Definition Documentation

◆ MAX_L10N_DATA

#define MAX_L10N_DATA   80

Definition at line 94 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 85 of file pg_locale.c.

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 147 of file pg_locale.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 148 of file pg_locale.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   collation_cache_entry

Definition at line 139 of file pg_locale.c.

◆ SH_EQUAL

#define SH_EQUAL (   tb,
  a,
  b 
)    (a == b)

Definition at line 143 of file pg_locale.c.

◆ SH_GET_HASH

#define SH_GET_HASH (   tb,
  a 
)    a->hash

Definition at line 144 of file pg_locale.c.

◆ SH_HASH_KEY

#define SH_HASH_KEY (   tb,
  key 
)    murmurhash32((uint32) key)

Definition at line 142 of file pg_locale.c.

◆ SH_KEY

#define SH_KEY   collid

Definition at line 141 of file pg_locale.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   Oid

Definition at line 140 of file pg_locale.c.

◆ SH_PREFIX

#define SH_PREFIX   collation_cache

Definition at line 138 of file pg_locale.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 145 of file pg_locale.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

Definition at line 146 of file pg_locale.c.

◆ TEXTBUFLEN

#define TEXTBUFLEN   1024

Definition at line 92 of file pg_locale.c.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 451 of file pg_locale.c.

452 {
453  /*
454  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
455  * We ignore failure, as per comment above.
456  */
457 #ifdef LC_MESSAGES
458  (void) pg_perm_setlocale(LC_MESSAGES, newval);
459 #endif
460 }
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:236

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 388 of file pg_locale.c.

389 {
390  CurrentLocaleConvValid = false;
391 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:123

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 400 of file pg_locale.c.

401 {
402  CurrentLocaleConvValid = false;
403 }

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 412 of file pg_locale.c.

413 {
414  CurrentLCTimeValid = false;
415 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:124

References CurrentLCTimeValid.

◆ builtin_locale_encoding()

int builtin_locale_encoding ( const char *  locale)

Definition at line 2450 of file pg_locale.c.

2451 {
2452  if (strcmp(locale, "C") == 0)
2453  return -1;
2454  if (strcmp(locale, "C.UTF-8") == 0)
2455  return PG_UTF8;
2456 
2457  ereport(ERROR,
2458  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2459  errmsg("invalid locale name \"%s\" for builtin provider",
2460  locale)));
2461 
2462  return 0; /* keep compiler quiet */
2463 }
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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 2471 of file pg_locale.c.

2472 {
2473  const char *canonical_name = NULL;
2474  int required_encoding;
2475 
2476  if (strcmp(locale, "C") == 0)
2477  canonical_name = "C";
2478  else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0)
2479  canonical_name = "C.UTF-8";
2480 
2481  if (!canonical_name)
2482  ereport(ERROR,
2483  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2484  errmsg("invalid locale name \"%s\" for builtin provider",
2485  locale)));
2486 
2487  required_encoding = builtin_locale_encoding(canonical_name);
2488  if (required_encoding >= 0 && encoding != required_encoding)
2489  ereport(ERROR,
2490  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2491  errmsg("encoding \"%s\" does not match locale \"%s\"",
2493 
2494  return canonical_name;
2495 }
int32 encoding
Definition: pg_database.h:41
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:2450
#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 createdb(), DefineCollation(), init_database_collation(), and pg_newlocale_from_collation().

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 830 of file pg_locale.c.

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

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 807 of file pg_locale.c.

808 {
809  char *ptr;
810  char *olddst;
811 
812  /* Convert the string to the database encoding, or validate it's OK */
813  ptr = pg_any_to_server(src, strlen(src), encoding);
814 
815  /* Store the string in long-lived storage, replacing any previous value */
816  olddst = *dst;
818  if (olddst)
819  pfree(olddst);
820 
821  /* Might as well clean up any palloc'd conversion result, too */
822  if (ptr != src)
823  pfree(ptr);
824 }
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:676
MemoryContext TopMemoryContext
Definition: mcxt.c:149
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1683

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 3048 of file pg_locale.c.

3050 {
3051  size_t result;
3052 
3053  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
3054 
3055  if (tolen == 0)
3056  return 0;
3057 
3058 #ifdef WIN32
3059  /* See WIN32 "Unicode" comment above */
3060  if (GetDatabaseEncoding() == PG_UTF8)
3061  {
3062  /* Win32 API does not work for zero-length input */
3063  if (fromlen == 0)
3064  result = 0;
3065  else
3066  {
3067  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
3068  /* A zero return is failure */
3069  if (result == 0)
3070  result = -1;
3071  }
3072 
3073  if (result != -1)
3074  {
3075  Assert(result < tolen);
3076  /* Append trailing null wchar (MultiByteToWideChar() does not) */
3077  to[result] = 0;
3078  }
3079  }
3080  else
3081 #endif /* WIN32 */
3082  {
3083  /* mbstowcs requires ending '\0' */
3084  char *str = pnstrdup(from, fromlen);
3085 
3086  if (locale == (pg_locale_t) 0)
3087  {
3088  /* Use mbstowcs directly for the default locale */
3089  result = mbstowcs(to, str, tolen);
3090  }
3091  else
3092  {
3093  /* Use mbstowcs_l for nondefault locales */
3094  result = mbstowcs_l(to, str, tolen, locale->info.lt);
3095  }
3096 
3097  pfree(str);
3098  }
3099 
3100  if (result == -1)
3101  {
3102  /*
3103  * Invalid multibyte character encountered. We try to give a useful
3104  * error message by letting pg_verifymbstr check the string. But it's
3105  * possible that the string is OK to us, and not OK to mbstowcs ---
3106  * this suggests that the LC_CTYPE locale is different from the
3107  * database encoding. Give a generic error message if pg_verifymbstr
3108  * can't find anything wrong.
3109  */
3110  pg_verifymbstr(from, fromlen, false); /* might not return */
3111  /* but if it does ... */
3112  ereport(ERROR,
3113  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
3114  errmsg("invalid multibyte character for locale"),
3115  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
3116  }
3117 
3118  return result;
3119 }
#define Assert(condition)
Definition: c.h:858
int errhint(const char *fmt,...)
Definition: elog.c:1317
const char * str
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:1707
static size_t mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc)
Definition: pg_locale.c:190

References Assert, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), locale, mbstowcs_l(), pfree(), PG_UTF8, pg_verifymbstr(), pnstrdup(), and 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 339 of file pg_locale.c.

340 {
341  char *save;
342  char *res;
343 
344  if (canonname)
345  *canonname = NULL; /* in case of failure */
346 
347  save = setlocale(category, NULL);
348  if (!save)
349  return false; /* won't happen, we hope */
350 
351  /* save may be pointing at a modifiable scratch variable, see above. */
352  save = pstrdup(save);
353 
354  /* set the locale with setlocale, to see if it accepts it. */
355  res = setlocale(category, locale);
356 
357  /* save canonical name if requested. */
358  if (res && canonname)
359  *canonname = pstrdup(res);
360 
361  /* restore old value. */
362  if (!setlocale(category, save))
363  elog(WARNING, "failed to restore old locale \"%s\"", save);
364  pfree(save);
365 
366  return (res != NULL);
367 }
#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 428 of file pg_locale.c.

429 {
430  if (**newval == '\0')
431  {
432  if (source == PGC_S_DEFAULT)
433  return true;
434  else
435  return false;
436  }
437 
438  /*
439  * LC_MESSAGES category does not exist everywhere, but accept it anyway
440  *
441  * On Windows, we can't even check the value, so accept blindly
442  */
443 #if defined(LC_MESSAGES) && !defined(WIN32)
444  return check_locale(LC_MESSAGES, *newval, NULL);
445 #else
446  return true;
447 #endif
448 }
@ PGC_S_DEFAULT
Definition: guc.h:109
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:339
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 382 of file pg_locale.c.

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

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 394 of file pg_locale.c.

395 {
396  return check_locale(LC_NUMERIC, *newval, NULL);
397 }

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 406 of file pg_locale.c.

407 {
408  return check_locale(LC_TIME, *newval, NULL);
409 }

References check_locale(), and newval.

◆ db_encoding_convert()

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

Definition at line 518 of file pg_locale.c.

519 {
520  char *pstr;
521  char *mstr;
522 
523  /* convert the string to the database encoding */
524  pstr = pg_any_to_server(*str, strlen(*str), encoding);
525  if (pstr == *str)
526  return; /* no conversion happened */
527 
528  /* need it malloc'd not palloc'd */
529  mstr = strdup(pstr);
530  if (mstr == NULL)
531  ereport(ERROR,
532  (errcode(ERRCODE_OUT_OF_MEMORY),
533  errmsg("out of memory")));
534 
535  /* replace old string */
536  free(*str);
537  *str = mstr;
538 
539  pfree(pstr);
540 }
#define free(a)
Definition: header.h:65

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

Referenced by PGLC_localeconv().

◆ free_struct_lconv()

static void free_struct_lconv ( struct lconv *  s)
static

Definition at line 468 of file pg_locale.c.

469 {
470  free(s->decimal_point);
471  free(s->thousands_sep);
472  free(s->grouping);
473  free(s->int_curr_symbol);
474  free(s->currency_symbol);
475  free(s->mon_decimal_point);
476  free(s->mon_thousands_sep);
477  free(s->mon_grouping);
478  free(s->positive_sign);
479  free(s->negative_sign);
480 }

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1659 of file pg_locale.c.

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

References buf, ereport, errcode(), 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 2851 of file pg_locale.c.

2852 {
2853 #ifdef USE_ICU
2854  UErrorCode status;
2855  char *langtag;
2856  size_t buflen = 32; /* arbitrary starting buffer size */
2857  const bool strict = true;
2858 
2859  /*
2860  * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
2861  * RFC5646 section 4.4). Additionally, in older ICU versions,
2862  * uloc_toLanguageTag() doesn't always return the ultimate length on the
2863  * first call, necessitating a loop.
2864  */
2865  langtag = palloc(buflen);
2866  while (true)
2867  {
2868  status = U_ZERO_ERROR;
2869  uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
2870 
2871  /* try again if the buffer is not large enough */
2872  if ((status == U_BUFFER_OVERFLOW_ERROR ||
2873  status == U_STRING_NOT_TERMINATED_WARNING) &&
2874  buflen < MaxAllocSize)
2875  {
2876  buflen = Min(buflen * 2, MaxAllocSize);
2877  langtag = repalloc(langtag, buflen);
2878  continue;
2879  }
2880 
2881  break;
2882  }
2883 
2884  if (U_FAILURE(status))
2885  {
2886  pfree(langtag);
2887 
2888  if (elevel > 0)
2889  ereport(elevel,
2890  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2891  errmsg("could not convert locale name \"%s\" to language tag: %s",
2892  loc_str, u_errorName(status))));
2893  return NULL;
2894  }
2895 
2896  return langtag;
2897 #else /* not USE_ICU */
2898  ereport(ERROR,
2899  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2900  errmsg("ICU is not supported in this build")));
2901  return NULL; /* keep compiler quiet */
2902 #endif /* not USE_ICU */
2903 }
#define Min(x, y)
Definition: c.h:1004
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * palloc(Size size)
Definition: mcxt.c:1317
#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 2909 of file pg_locale.c.

2910 {
2911 #ifdef USE_ICU
2912  UCollator *collator;
2913  UErrorCode status;
2914  char lang[ULOC_LANG_CAPACITY];
2915  bool found = false;
2916  int elevel = icu_validation_level;
2917 
2918  /* no validation */
2919  if (elevel < 0)
2920  return;
2921 
2922  /* downgrade to WARNING during pg_upgrade */
2923  if (IsBinaryUpgrade && elevel > WARNING)
2924  elevel = WARNING;
2925 
2926  /* validate that we can extract the language */
2927  status = U_ZERO_ERROR;
2928  uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
2929  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2930  {
2931  ereport(elevel,
2932  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2933  errmsg("could not get language from ICU locale \"%s\": %s",
2934  loc_str, u_errorName(status)),
2935  errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
2936  "icu_validation_level", "disabled")));
2937  return;
2938  }
2939 
2940  /* check for special language name */
2941  if (strcmp(lang, "") == 0 ||
2942  strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
2943  found = true;
2944 
2945  /* search for matching language within ICU */
2946  for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
2947  {
2948  const char *otherloc = uloc_getAvailable(i);
2949  char otherlang[ULOC_LANG_CAPACITY];
2950 
2951  status = U_ZERO_ERROR;
2952  uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
2953  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2954  continue;
2955 
2956  if (strcmp(lang, otherlang) == 0)
2957  found = true;
2958  }
2959 
2960  if (!found)
2961  ereport(elevel,
2962  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2963  errmsg("ICU locale \"%s\" has unknown language \"%s\"",
2964  loc_str, lang),
2965  errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
2966  "icu_validation_level", "disabled")));
2967 
2968  /* check that it can be opened */
2969  collator = pg_ucol_open(loc_str);
2970  ucol_close(collator);
2971 #else /* not USE_ICU */
2972  /* could get here if a collation was created by a build with ICU */
2973  ereport(ERROR,
2974  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2975  errmsg("ICU is not supported in this build")));
2976 #endif /* not USE_ICU */
2977 }
bool IsBinaryUpgrade
Definition: globals.c:120
int icu_validation_level
Definition: pg_locale.c:103

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

Referenced by createdb(), and DefineCollation().

◆ init_database_collation()

void init_database_collation ( void  )

Definition at line 1422 of file pg_locale.c.

1423 {
1424  HeapTuple tup;
1425  Form_pg_database dbform;
1426  Datum datum;
1427  bool isnull;
1428 
1429  /* Fetch our pg_database row normally, via syscache */
1430  tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
1431  if (!HeapTupleIsValid(tup))
1432  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1433  dbform = (Form_pg_database) GETSTRUCT(tup);
1434 
1435  if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
1436  {
1437  char *datlocale;
1438 
1439  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
1440  datlocale = TextDatumGetCString(datum);
1441 
1442  builtin_validate_locale(dbform->encoding, datlocale);
1443 
1445  default_locale.ctype_is_c = (strcmp(datlocale, "C") == 0);
1446 
1449  }
1450  else if (dbform->datlocprovider == COLLPROVIDER_ICU)
1451  {
1452  char *datlocale;
1453  char *icurules;
1454 
1455  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
1456  datlocale = TextDatumGetCString(datum);
1457 
1458  default_locale.collate_is_c = false;
1459  default_locale.ctype_is_c = false;
1460 
1461  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
1462  if (!isnull)
1463  icurules = TextDatumGetCString(datum);
1464  else
1465  icurules = NULL;
1466 
1468  }
1469  else
1470  {
1471  const char *datcollate;
1472  const char *datctype;
1473 
1474  Assert(dbform->datlocprovider == COLLPROVIDER_LIBC);
1475 
1476  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
1477  datcollate = TextDatumGetCString(datum);
1478  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
1479  datctype = TextDatumGetCString(datum);
1480 
1481  default_locale.collate_is_c = (strcmp(datcollate, "C") == 0) ||
1482  (strcmp(datcollate, "POSIX") == 0);
1483  default_locale.ctype_is_c = (strcmp(datctype, "C") == 0) ||
1484  (strcmp(datctype, "POSIX") == 0);
1485 
1486  make_libc_collator(datcollate, datctype, &default_locale);
1487  }
1488 
1489  default_locale.provider = dbform->datlocprovider;
1490 
1491  /*
1492  * Default locale is currently always deterministic. Nondeterministic
1493  * locales currently don't support pattern matching, which would break a
1494  * lot of things if applied globally.
1495  */
1497 
1498  ReleaseSysCache(tup);
1499 }
#define TextDatumGetCString(d)
Definition: builtins.h:98
Oid MyDatabaseId
Definition: globals.c:93
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static char * datlocale
Definition: initdb.c:149
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1367
static struct pg_locale_struct default_locale
Definition: pg_locale.c:120
static void make_libc_collator(const char *collate, const char *ctype, pg_locale_t result)
Definition: pg_locale.c:1306
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:2471
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
union pg_locale_struct::@153 info
struct pg_locale_struct::@153::@154 builtin
bool deterministic
Definition: pg_locale.h:85
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510

References Assert, pg_locale_struct::builtin, builtin_validate_locale(), pg_locale_struct::collate_is_c, pg_locale_struct::ctype_is_c, datlocale, default_locale, pg_locale_struct::deterministic, elog, ERROR, GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, make_icu_collator(), make_libc_collator(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), pg_locale_struct::provider, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, and TopMemoryContext.

Referenced by CheckMyDatabase().

◆ lookup_collation_cache()

static collation_cache_entry* lookup_collation_cache ( Oid  collation)
static

Definition at line 1239 of file pg_locale.c.

1240 {
1241  collation_cache_entry *cache_entry;
1242  bool found;
1243 
1244  Assert(OidIsValid(collation));
1245  Assert(collation != DEFAULT_COLLATION_OID);
1246 
1247  if (CollationCache == NULL)
1248  {
1250  "collation cache",
1252  CollationCache = collation_cache_create(CollationCacheContext,
1253  16, NULL);
1254  }
1255 
1256  cache_entry = collation_cache_insert(CollationCache, collation, &found);
1257  if (!found)
1258  {
1259  /*
1260  * Make sure cache entry is marked invalid, in case we fail before
1261  * setting things.
1262  */
1263  cache_entry->locale = 0;
1264  }
1265 
1266  return cache_entry;
1267 }
#define OidIsValid(objectId)
Definition: c.h:775
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static MemoryContext CollationCacheContext
Definition: pg_locale.c:151
static collation_cache_hash * CollationCache
Definition: pg_locale.c:152
Definition: pg_locale.c:129
pg_locale_t locale
Definition: pg_locale.c:131

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CollationCache, CollationCacheContext, collation_cache_entry::locale, OidIsValid, and TopMemoryContext.

Referenced by 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 1367 of file pg_locale.c.

1370 {
1371 #ifdef USE_ICU
1372  UCollator *collator;
1373 
1374  collator = pg_ucol_open(iculocstr);
1375 
1376  /*
1377  * If rules are specified, we extract the rules of the standard collation,
1378  * add our own rules, and make a new collator with the combined rules.
1379  */
1380  if (icurules)
1381  {
1382  const UChar *default_rules;
1383  UChar *agg_rules;
1384  UChar *my_rules;
1385  UErrorCode status;
1386  int32_t length;
1387 
1388  default_rules = ucol_getRules(collator, &length);
1389  icu_to_uchar(&my_rules, icurules, strlen(icurules));
1390 
1391  agg_rules = palloc_array(UChar, u_strlen(default_rules) + u_strlen(my_rules) + 1);
1392  u_strcpy(agg_rules, default_rules);
1393  u_strcat(agg_rules, my_rules);
1394 
1395  ucol_close(collator);
1396 
1397  status = U_ZERO_ERROR;
1398  collator = ucol_openRules(agg_rules, u_strlen(agg_rules),
1399  UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
1400  if (U_FAILURE(status))
1401  ereport(ERROR,
1402  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1403  errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s",
1404  iculocstr, icurules, u_errorName(status))));
1405  }
1406 
1407  /* We will leak this string if the caller errors later :-( */
1408  resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1409  resultp->info.icu.ucol = collator;
1410 #else /* not USE_ICU */
1411  /* could get here if a collation was created by a build with ICU */
1412  ereport(ERROR,
1413  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1414  errmsg("ICU is not supported in this build")));
1415 #endif /* not USE_ICU */
1416 }
#define palloc_array(type, count)
Definition: fe_memutils.h:64
const char * locale
Definition: pg_locale.h:92

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

Referenced by init_database_collation(), and pg_newlocale_from_collation().

◆ make_libc_collator()

static void make_libc_collator ( const char *  collate,
const char *  ctype,
pg_locale_t  result 
)
static

Definition at line 1306 of file pg_locale.c.

1308 {
1309  locale_t loc = 0;
1310 
1311  if (strcmp(collate, ctype) == 0)
1312  {
1313  if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0)
1314  {
1315  /* Normal case where they're the same */
1316  errno = 0;
1317 #ifndef WIN32
1318  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collate,
1319  NULL);
1320 #else
1321  loc = _create_locale(LC_ALL, collate);
1322 #endif
1323  if (!loc)
1324  report_newlocale_failure(collate);
1325  }
1326  }
1327  else
1328  {
1329 #ifndef WIN32
1330  /* We need two newlocale() steps */
1331  locale_t loc1 = 0;
1332 
1333  if (strcmp(collate, "C") != 0 && strcmp(collate, "POSIX") != 0)
1334  {
1335  errno = 0;
1336  loc1 = newlocale(LC_COLLATE_MASK, collate, NULL);
1337  if (!loc1)
1338  report_newlocale_failure(collate);
1339  }
1340 
1341  if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0)
1342  {
1343  errno = 0;
1344  loc = newlocale(LC_CTYPE_MASK, ctype, loc1);
1345  if (!loc)
1346  report_newlocale_failure(ctype);
1347  }
1348  else
1349  loc = loc1;
1350 #else
1351 
1352  /*
1353  * XXX The _create_locale() API doesn't appear to support this. Could
1354  * perhaps be worked around by changing pg_locale_t to contain two
1355  * separate fields.
1356  */
1357  ereport(ERROR,
1358  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1359  errmsg("collations with different collate and ctype values are not supported on this platform")));
1360 #endif
1361  }
1362 
1363  result->info.lt = loc;
1364 }
static void report_newlocale_failure(const char *localename)
Definition: pg_locale.c:1271
locale_t lt
Definition: pg_locale.h:94

References ereport, errcode(), errmsg(), ERROR, pg_locale_struct::info, locale_t, pg_locale_struct::lt, and report_newlocale_failure().

Referenced by init_database_collation(), 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 190 of file pg_locale.c.

191 {
192 #ifdef WIN32
193  return _mbstowcs_l(dest, src, n, loc);
194 #else
195  size_t result;
196  locale_t save_locale = uselocale(loc);
197 
198  result = mbstowcs(dest, src, n);
199  uselocale(save_locale);
200  return result;
201 #endif
202 }

References generate_unaccent_rules::dest, and locale_t.

Referenced by char2wchar().

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1510 of file pg_locale.c.

1511 {
1512  collation_cache_entry *cache_entry;
1513 
1514  if (collid == DEFAULT_COLLATION_OID)
1515  return &default_locale;
1516 
1517  if (!OidIsValid(collid))
1518  elog(ERROR, "cache lookup failed for collation %u", collid);
1519 
1522 
1523  cache_entry = lookup_collation_cache(collid);
1524 
1525  if (cache_entry->locale == 0)
1526  {
1527  /* We haven't computed this yet in this session, so do it */
1528  HeapTuple tp;
1529  Form_pg_collation collform;
1530  struct pg_locale_struct result;
1531  pg_locale_t resultp;
1532  Datum datum;
1533  bool isnull;
1534 
1535  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1536  if (!HeapTupleIsValid(tp))
1537  elog(ERROR, "cache lookup failed for collation %u", collid);
1538  collform = (Form_pg_collation) GETSTRUCT(tp);
1539 
1540  /* We'll fill in the result struct locally before allocating memory */
1541  memset(&result, 0, sizeof(result));
1542  result.provider = collform->collprovider;
1543  result.deterministic = collform->collisdeterministic;
1544 
1545  if (collform->collprovider == COLLPROVIDER_BUILTIN)
1546  {
1547  const char *locstr;
1548 
1549  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1550  locstr = TextDatumGetCString(datum);
1551 
1552  result.collate_is_c = true;
1553  result.ctype_is_c = (strcmp(locstr, "C") == 0);
1554 
1556 
1557  result.info.builtin.locale = MemoryContextStrdup(TopMemoryContext,
1558  locstr);
1559  }
1560  else if (collform->collprovider == COLLPROVIDER_LIBC)
1561  {
1562  const char *collcollate;
1563  const char *collctype;
1564 
1565  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1566  collcollate = TextDatumGetCString(datum);
1567  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1568  collctype = TextDatumGetCString(datum);
1569 
1570  result.collate_is_c = (strcmp(collcollate, "C") == 0) ||
1571  (strcmp(collcollate, "POSIX") == 0);
1572  result.ctype_is_c = (strcmp(collctype, "C") == 0) ||
1573  (strcmp(collctype, "POSIX") == 0);
1574 
1575  make_libc_collator(collcollate, collctype, &result);
1576  }
1577  else if (collform->collprovider == COLLPROVIDER_ICU)
1578  {
1579  const char *iculocstr;
1580  const char *icurules;
1581 
1582  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1583  iculocstr = TextDatumGetCString(datum);
1584 
1585  result.collate_is_c = false;
1586  result.ctype_is_c = false;
1587 
1588  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1589  if (!isnull)
1590  icurules = TextDatumGetCString(datum);
1591  else
1592  icurules = NULL;
1593 
1594  make_icu_collator(iculocstr, icurules, &result);
1595  }
1596 
1597  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1598  &isnull);
1599  if (!isnull)
1600  {
1601  char *actual_versionstr;
1602  char *collversionstr;
1603 
1604  collversionstr = TextDatumGetCString(datum);
1605 
1606  if (collform->collprovider == COLLPROVIDER_LIBC)
1607  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1608  else
1609  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1610 
1611  actual_versionstr = get_collation_actual_version(collform->collprovider,
1612  TextDatumGetCString(datum));
1613  if (!actual_versionstr)
1614  {
1615  /*
1616  * This could happen when specifying a version in CREATE
1617  * COLLATION but the provider does not support versioning, or
1618  * manually creating a mess in the catalogs.
1619  */
1620  ereport(ERROR,
1621  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1622  NameStr(collform->collname))));
1623  }
1624 
1625  if (strcmp(actual_versionstr, collversionstr) != 0)
1626  ereport(WARNING,
1627  (errmsg("collation \"%s\" has version mismatch",
1628  NameStr(collform->collname)),
1629  errdetail("The collation in the database was created using version %s, "
1630  "but the operating system provides version %s.",
1631  collversionstr, actual_versionstr),
1632  errhint("Rebuild all objects affected by this collation and run "
1633  "ALTER COLLATION %s REFRESH VERSION, "
1634  "or build PostgreSQL with the right library version.",
1635  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1636  NameStr(collform->collname)))));
1637  }
1638 
1639  ReleaseSysCache(tp);
1640 
1641  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1642  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1643  *resultp = result;
1644 
1645  cache_entry->locale = resultp;
1646  }
1647 
1649  last_collation_cache_locale = cache_entry->locale;
1650 
1651  return cache_entry->locale;
1652 }
#define NameStr(name)
Definition: c.h:746
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1203
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
static pg_locale_t last_collation_cache_locale
Definition: pg_locale.c:159
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1659
static collation_cache_entry * lookup_collation_cache(Oid collation)
Definition: pg_locale.c:1239
static Oid last_collation_cache_oid
Definition: pg_locale.c:158
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12924

References pg_locale_struct::builtin, builtin_validate_locale(), pg_locale_struct::collate_is_c, collid, pg_locale_struct::ctype_is_c, default_locale, pg_locale_struct::deterministic, elog, ereport, errdetail(), errhint(), errmsg(), ERROR, get_collation_actual_version(), get_namespace_name(), GetDatabaseEncoding(), GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, last_collation_cache_locale, last_collation_cache_oid, collation_cache_entry::locale, lookup_collation_cache(), make_icu_collator(), make_libc_collator(), MemoryContextAlloc(), MemoryContextStrdup(), NameStr, ObjectIdGetDatum(), OidIsValid, pg_locale_struct::provider, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, TopMemoryContext, and WARNING.

Referenced by bpchareq(), bpcharne(), btvarstrequalimage(), convert_string_datum(), DefineCollation(), Generic_Text_IC_like(), GenericMatchText(), hashbpchar(), hashbpcharextended(), hashtext(), hashtextextended(), like_fixed_prefix(), make_greater_string(), match_pattern_prefix(), pg_set_regex_collation(), spg_text_inner_consistent(), 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 236 of file pg_locale.c.

237 {
238  char *result;
239  const char *envvar;
240 
241 #ifndef WIN32
242  result = setlocale(category, locale);
243 #else
244 
245  /*
246  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
247  * the given value is good and set it in the environment variables. We
248  * must ignore attempts to set to "", which means "keep using the old
249  * environment value".
250  */
251 #ifdef LC_MESSAGES
252  if (category == LC_MESSAGES)
253  {
254  result = (char *) locale;
255  if (locale == NULL || locale[0] == '\0')
256  return result;
257  }
258  else
259 #endif
260  result = setlocale(category, locale);
261 #endif /* WIN32 */
262 
263  if (result == NULL)
264  return result; /* fall out immediately on failure */
265 
266  /*
267  * Use the right encoding in translated messages. Under ENABLE_NLS, let
268  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
269  * format strings are ASCII, but database-encoding strings may enter the
270  * message via %s. This makes the overall message encoding equal to the
271  * database encoding.
272  */
273  if (category == LC_CTYPE)
274  {
275  static char save_lc_ctype[LOCALE_NAME_BUFLEN];
276 
277  /* copy setlocale() return value before callee invokes it again */
278  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
279  result = save_lc_ctype;
280 
281 #ifdef ENABLE_NLS
282  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
283 #else
285 #endif
286  }
287 
288  switch (category)
289  {
290  case LC_COLLATE:
291  envvar = "LC_COLLATE";
292  break;
293  case LC_CTYPE:
294  envvar = "LC_CTYPE";
295  break;
296 #ifdef LC_MESSAGES
297  case LC_MESSAGES:
298  envvar = "LC_MESSAGES";
299 #ifdef WIN32
300  result = IsoLocaleName(locale);
301  if (result == NULL)
302  result = (char *) locale;
303  elog(DEBUG3, "IsoLocaleName() executed; locale: \"%s\"", result);
304 #endif /* WIN32 */
305  break;
306 #endif /* LC_MESSAGES */
307  case LC_MONETARY:
308  envvar = "LC_MONETARY";
309  break;
310  case LC_NUMERIC:
311  envvar = "LC_NUMERIC";
312  break;
313  case LC_TIME:
314  envvar = "LC_TIME";
315  break;
316  default:
317  elog(FATAL, "unrecognized LC category: %d", category);
318  return NULL; /* keep compiler quiet */
319  }
320 
321  if (setenv(envvar, result, 1) != 0)
322  return NULL;
323 
324  return result;
325 }
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:555

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 2022 of file pg_locale.c.

2023 {
2024  int result;
2025 
2026  if (locale->provider == COLLPROVIDER_LIBC)
2027  result = pg_strcoll_libc(arg1, arg2, locale);
2028 #ifdef USE_ICU
2029  else if (locale->provider == COLLPROVIDER_ICU)
2030  result = pg_strncoll_icu(arg1, -1, arg2, -1, locale);
2031 #endif
2032  else
2033  /* shouldn't happen */
2034  PGLOCALE_SUPPORT_ERROR(locale->provider);
2035 
2036  return result;
2037 }
#define PGLOCALE_SUPPORT_ERROR(provider)
Definition: pg_locale.c:85
static int pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale)
Definition: pg_locale.c:1843

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 1843 of file pg_locale.c.

1844 {
1845  int result;
1846 
1847  Assert(locale->provider == COLLPROVIDER_LIBC);
1848 #ifdef WIN32
1849  if (GetDatabaseEncoding() == PG_UTF8)
1850  {
1851  size_t len1 = strlen(arg1);
1852  size_t len2 = strlen(arg2);
1853 
1854  result = pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1855  }
1856  else
1857 #endif /* WIN32 */
1858  result = strcoll_l(arg1, arg2, locale->info.lt);
1859 
1860  return result;
1861 }
#define strcoll_l
Definition: win32_port.h:465

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 2057 of file pg_locale.c.

2059 {
2060  int result;
2061 
2062  if (locale->provider == COLLPROVIDER_LIBC)
2063  result = pg_strncoll_libc(arg1, len1, arg2, len2, locale);
2064 #ifdef USE_ICU
2065  else if (locale->provider == COLLPROVIDER_ICU)
2066  result = pg_strncoll_icu(arg1, len1, arg2, len2, locale);
2067 #endif
2068  else
2069  /* shouldn't happen */
2070  PGLOCALE_SUPPORT_ERROR(locale->provider);
2071 
2072  return result;
2073 }
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:1869

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 1869 of file pg_locale.c.

1871 {
1872  char sbuf[TEXTBUFLEN];
1873  char *buf = sbuf;
1874  size_t bufsize1 = len1 + 1;
1875  size_t bufsize2 = len2 + 1;
1876  char *arg1n;
1877  char *arg2n;
1878  int result;
1879 
1880  Assert(locale->provider == COLLPROVIDER_LIBC);
1881 
1882 #ifdef WIN32
1883  /* check for this case before doing the work for nul-termination */
1884  if (GetDatabaseEncoding() == PG_UTF8)
1885  return pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1886 #endif /* WIN32 */
1887 
1888  if (bufsize1 + bufsize2 > TEXTBUFLEN)
1889  buf = palloc(bufsize1 + bufsize2);
1890 
1891  arg1n = buf;
1892  arg2n = buf + bufsize1;
1893 
1894  /* nul-terminate arguments */
1895  memcpy(arg1n, arg1, len1);
1896  arg1n[len1] = '\0';
1897  memcpy(arg2n, arg2, len2);
1898  arg2n[len2] = '\0';
1899 
1900  result = pg_strcoll_libc(arg1n, arg2n, locale);
1901 
1902  if (buf != sbuf)
1903  pfree(buf);
1904 
1905  return result;
1906 }
#define TEXTBUFLEN
Definition: pg_locale.c:92

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 2339 of file pg_locale.c.

2341 {
2342  size_t result = 0; /* keep compiler quiet */
2343 
2344  if (locale->provider == COLLPROVIDER_LIBC)
2345  result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale);
2346 #ifdef USE_ICU
2347  else if (locale->provider == COLLPROVIDER_ICU)
2348  result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale);
2349 #endif
2350  else
2351  /* shouldn't happen */
2352  PGLOCALE_SUPPORT_ERROR(locale->provider);
2353 
2354  return result;
2355 }
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:2085

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 2085 of file pg_locale.c.

2087 {
2088  char sbuf[TEXTBUFLEN];
2089  char *buf = sbuf;
2090  size_t bufsize = srclen + 1;
2091  size_t result;
2092 
2093  Assert(locale->provider == COLLPROVIDER_LIBC);
2094 
2095  if (bufsize > TEXTBUFLEN)
2096  buf = palloc(bufsize);
2097 
2098  /* nul-terminate arguments */
2099  memcpy(buf, src, srclen);
2100  buf[srclen] = '\0';
2101 
2102  result = pg_strxfrm_libc(dest, buf, destsize, locale);
2103 
2104  if (buf != sbuf)
2105  pfree(buf);
2106 
2107  /* if dest is defined, it should be nul-terminated */
2108  Assert(result >= destsize || dest[result] == '\0');
2109 
2110  return result;
2111 }
#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:2077

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 2430 of file pg_locale.c.

2432 {
2433  size_t result = 0; /* keep compiler quiet */
2434 
2435 #ifdef USE_ICU
2436  if (locale->provider == COLLPROVIDER_ICU)
2437  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2438  else
2439 #endif
2440  PGLOCALE_SUPPORT_ERROR(locale->provider);
2441 
2442  return result;
2443 }

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 2299 of file pg_locale.c.

2300 {
2301  size_t result = 0; /* keep compiler quiet */
2302 
2303  if (locale->provider == COLLPROVIDER_LIBC)
2304  result = pg_strxfrm_libc(dest, src, destsize, locale);
2305 #ifdef USE_ICU
2306  else if (locale->provider == COLLPROVIDER_ICU)
2307  result = pg_strnxfrm_icu(dest, src, -1, destsize, locale);
2308 #endif
2309  else
2310  /* shouldn't happen */
2311  PGLOCALE_SUPPORT_ERROR(locale->provider);
2312 
2313  return result;
2314 }

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

Referenced by convert_string_datum(), and varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 2263 of file pg_locale.c.

2264 {
2265  if (locale->provider == COLLPROVIDER_LIBC)
2266 #ifdef TRUST_STRXFRM
2267  return true;
2268 #else
2269  return false;
2270 #endif
2271  else if (locale->provider == COLLPROVIDER_ICU)
2272  return true;
2273  else
2274  /* shouldn't happen */
2275  PGLOCALE_SUPPORT_ERROR(locale->provider);
2276 
2277  return false; /* keep compiler quiet */
2278 }

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 2077 of file pg_locale.c.

2079 {
2080  Assert(locale->provider == COLLPROVIDER_LIBC);
2081  return strxfrm_l(dest, src, destsize, locale->info.lt);
2082 }
#define strxfrm_l
Definition: win32_port.h:466

References Assert, generate_unaccent_rules::dest, locale, 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 2393 of file pg_locale.c.

2395 {
2396  size_t result = 0; /* keep compiler quiet */
2397 
2398 #ifdef USE_ICU
2399  if (locale->provider == COLLPROVIDER_ICU)
2400  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2401  else
2402 #endif
2403  PGLOCALE_SUPPORT_ERROR(locale->provider);
2404 
2405  return result;
2406 }

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 2362 of file pg_locale.c.

2363 {
2364  if (locale->provider == COLLPROVIDER_LIBC)
2365  return false;
2366  else if (locale->provider == COLLPROVIDER_ICU)
2367  return true;
2368  else
2369  /* shouldn't happen */
2370  PGLOCALE_SUPPORT_ERROR(locale->provider);
2371 
2372  return false; /* keep compiler quiet */
2373 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 548 of file pg_locale.c.

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

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 1271 of file pg_locale.c.

1272 {
1273  int save_errno;
1274 
1275  /*
1276  * Windows doesn't provide any useful error indication from
1277  * _create_locale(), and BSD-derived platforms don't seem to feel they
1278  * need to set errno either (even though POSIX is pretty clear that
1279  * newlocale should do so). So, if errno hasn't been set, assume ENOENT
1280  * is what to report.
1281  */
1282  if (errno == 0)
1283  errno = ENOENT;
1284 
1285  /*
1286  * ENOENT means "no such locale", not "no such file", so clarify that
1287  * errno with an errdetail message.
1288  */
1289  save_errno = errno; /* auxiliary funcs might change errno */
1290  ereport(ERROR,
1291  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1292  errmsg("could not create locale \"%s\": %m",
1293  localename),
1294  (save_errno == ENOENT ?
1295  errdetail("The operating system could not find any locale data for the locale name \"%s\".",
1296  localename) : 0)));
1297 }

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

Referenced by make_libc_collator().

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 487 of file pg_locale.c.

488 {
489  if (s->decimal_point == NULL)
490  return false;
491  if (s->thousands_sep == NULL)
492  return false;
493  if (s->grouping == NULL)
494  return false;
495  if (s->int_curr_symbol == NULL)
496  return false;
497  if (s->currency_symbol == NULL)
498  return false;
499  if (s->mon_decimal_point == NULL)
500  return false;
501  if (s->mon_thousands_sep == NULL)
502  return false;
503  if (s->mon_grouping == NULL)
504  return false;
505  if (s->positive_sign == NULL)
506  return false;
507  if (s->negative_sign == NULL)
508  return false;
509  return true;
510 }

Referenced by PGLC_localeconv().

◆ wchar2char()

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

Definition at line 2992 of file pg_locale.c.

2993 {
2994  size_t result;
2995 
2996  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2997 
2998  if (tolen == 0)
2999  return 0;
3000 
3001 #ifdef WIN32
3002 
3003  /*
3004  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
3005  * for some reason mbstowcs and wcstombs won't do this for us, so we use
3006  * MultiByteToWideChar().
3007  */
3008  if (GetDatabaseEncoding() == PG_UTF8)
3009  {
3010  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
3011  NULL, NULL);
3012  /* A zero return is failure */
3013  if (result <= 0)
3014  result = -1;
3015  else
3016  {
3017  Assert(result <= tolen);
3018  /* Microsoft counts the zero terminator in the result */
3019  result--;
3020  }
3021  }
3022  else
3023 #endif /* WIN32 */
3024  if (locale == (pg_locale_t) 0)
3025  {
3026  /* Use wcstombs directly for the default locale */
3027  result = wcstombs(to, from, tolen);
3028  }
3029  else
3030  {
3031  /* Use wcstombs_l for nondefault locales */
3032  result = wcstombs_l(to, from, tolen, locale->info.lt);
3033  }
3034 
3035  return result;
3036 }
static size_t wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc)
Definition: pg_locale.c:206

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 206 of file pg_locale.c.

207 {
208 #ifdef WIN32
209  return _wcstombs_l(dest, src, n, loc);
210 #else
211  size_t result;
212  locale_t save_locale = uselocale(loc);
213 
214  result = wcstombs(dest, src, n);
215  uselocale(save_locale);
216  return result;
217 #endif
218 }

References generate_unaccent_rules::dest, and locale_t.

Referenced by wchar2char().

Variable Documentation

◆ CollationCache

collation_cache_hash* CollationCache = NULL
static

Definition at line 152 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CollationCacheContext

MemoryContext CollationCacheContext = NULL
static

Definition at line 151 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 124 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 123 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
static

Definition at line 118 of file pg_locale.c.

Referenced by init_database_collation(), and pg_newlocale_from_collation().

◆ icu_validation_level

int icu_validation_level = WARNING

Definition at line 103 of file pg_locale.c.

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

◆ last_collation_cache_locale

pg_locale_t last_collation_cache_locale = NULL
static

Definition at line 159 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ last_collation_cache_oid

Oid last_collation_cache_oid = InvalidOid
static

Definition at line 158 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ locale_messages

char* locale_messages

Definition at line 98 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 99 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 100 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 101 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_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_abbrev_months

char* localized_abbrev_months[12+1]

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

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