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 "common/string.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

locale_t make_libc_collator (const char *collate, const char *ctype)
 
int strncoll_libc (const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale)
 
size_t strnxfrm_libc (char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
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)
 
void init_database_collation (void)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
int pg_strcoll (const char *arg1, const char *arg2, pg_locale_t locale)
 
int pg_strncoll (const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, 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, ssize_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, ssize_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)
 

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

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 168 of file pg_locale.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 169 of file pg_locale.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   collation_cache_entry

Definition at line 160 of file pg_locale.c.

◆ SH_EQUAL

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

Definition at line 164 of file pg_locale.c.

◆ SH_GET_HASH

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

Definition at line 165 of file pg_locale.c.

◆ SH_HASH_KEY

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

Definition at line 163 of file pg_locale.c.

◆ SH_KEY

#define SH_KEY   collid

Definition at line 162 of file pg_locale.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   Oid

Definition at line 161 of file pg_locale.c.

◆ SH_PREFIX

#define SH_PREFIX   collation_cache

Definition at line 159 of file pg_locale.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 166 of file pg_locale.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

Definition at line 167 of file pg_locale.c.

◆ TEXTBUFLEN

#define TEXTBUFLEN   1024

Definition at line 88 of file pg_locale.c.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 438 of file pg_locale.c.

439 {
440  /*
441  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
442  * We ignore failure, as per comment above.
443  */
444 #ifdef LC_MESSAGES
445  (void) pg_perm_setlocale(LC_MESSAGES, newval);
446 #endif
447 }
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:201

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 375 of file pg_locale.c.

376 {
377  CurrentLocaleConvValid = false;
378 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:144

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 387 of file pg_locale.c.

388 {
389  CurrentLocaleConvValid = false;
390 }

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 399 of file pg_locale.c.

400 {
401  CurrentLCTimeValid = false;
402 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:145

References CurrentLCTimeValid.

◆ builtin_locale_encoding()

int builtin_locale_encoding ( const char *  locale)

Definition at line 1838 of file pg_locale.c.

1839 {
1840  if (strcmp(locale, "C") == 0)
1841  return -1;
1842  if (strcmp(locale, "C.UTF-8") == 0)
1843  return PG_UTF8;
1844 
1845  ereport(ERROR,
1846  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1847  errmsg("invalid locale name \"%s\" for builtin provider",
1848  locale)));
1849 
1850  return 0; /* keep compiler quiet */
1851 }
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 1859 of file pg_locale.c.

1860 {
1861  const char *canonical_name = NULL;
1862  int required_encoding;
1863 
1864  if (strcmp(locale, "C") == 0)
1865  canonical_name = "C";
1866  else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0)
1867  canonical_name = "C.UTF-8";
1868 
1869  if (!canonical_name)
1870  ereport(ERROR,
1871  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1872  errmsg("invalid locale name \"%s\" for builtin provider",
1873  locale)));
1874 
1875  required_encoding = builtin_locale_encoding(canonical_name);
1876  if (required_encoding >= 0 && encoding != required_encoding)
1877  ereport(ERROR,
1878  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1879  errmsg("encoding \"%s\" does not match locale \"%s\"",
1881 
1882  return canonical_name;
1883 }
int32 encoding
Definition: pg_database.h:41
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:1838
#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 817 of file pg_locale.c.

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

795 {
796  char *ptr;
797  char *olddst;
798 
799  /* Convert the string to the database encoding, or validate it's OK */
800  ptr = pg_any_to_server(src, strlen(src), encoding);
801 
802  /* Store the string in long-lived storage, replacing any previous value */
803  olddst = *dst;
805  if (olddst)
806  pfree(olddst);
807 
808  /* Might as well clean up any palloc'd conversion result, too */
809  if (ptr != src)
810  pfree(ptr);
811 }
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().

◆ check_locale()

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

Definition at line 304 of file pg_locale.c.

305 {
306  char *save;
307  char *res;
308 
309  /* Don't let Windows' non-ASCII locale names in. */
310  if (!pg_is_ascii(locale))
311  {
313  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
314  errmsg("locale name \"%s\" contains non-ASCII characters",
315  locale)));
316  return false;
317  }
318 
319  if (canonname)
320  *canonname = NULL; /* in case of failure */
321 
322  save = setlocale(category, NULL);
323  if (!save)
324  return false; /* won't happen, we hope */
325 
326  /* save may be pointing at a modifiable scratch variable, see above. */
327  save = pstrdup(save);
328 
329  /* set the locale with setlocale, to see if it accepts it. */
330  res = setlocale(category, locale);
331 
332  /* save canonical name if requested. */
333  if (res && canonname)
334  *canonname = pstrdup(res);
335 
336  /* restore old value. */
337  if (!setlocale(category, save))
338  elog(WARNING, "failed to restore old locale \"%s\"", save);
339  pfree(save);
340 
341  /* Don't let Windows' non-ASCII locale names out. */
342  if (canonname && *canonname && !pg_is_ascii(*canonname))
343  {
345  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
346  errmsg("locale name \"%s\" contains non-ASCII characters",
347  *canonname)));
348  pfree(*canonname);
349  *canonname = NULL;
350  return false;
351  }
352 
353  return (res != NULL);
354 }
#define WARNING
Definition: elog.h:36
bool pg_is_ascii(const char *str)
Definition: string.c:133

References elog, ereport, errcode(), errmsg(), locale, pfree(), pg_is_ascii(), 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 415 of file pg_locale.c.

416 {
417  if (**newval == '\0')
418  {
419  if (source == PGC_S_DEFAULT)
420  return true;
421  else
422  return false;
423  }
424 
425  /*
426  * LC_MESSAGES category does not exist everywhere, but accept it anyway
427  *
428  * On Windows, we can't even check the value, so accept blindly
429  */
430 #if defined(LC_MESSAGES) && !defined(WIN32)
431  return check_locale(LC_MESSAGES, *newval, NULL);
432 #else
433  return true;
434 #endif
435 }
@ PGC_S_DEFAULT
Definition: guc.h:109
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:304
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 369 of file pg_locale.c.

370 {
371  return check_locale(LC_MONETARY, *newval, NULL);
372 }

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 381 of file pg_locale.c.

382 {
383  return check_locale(LC_NUMERIC, *newval, NULL);
384 }

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 393 of file pg_locale.c.

394 {
395  return check_locale(LC_TIME, *newval, NULL);
396 }

References check_locale(), and newval.

◆ db_encoding_convert()

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

Definition at line 505 of file pg_locale.c.

506 {
507  char *pstr;
508  char *mstr;
509 
510  /* convert the string to the database encoding */
511  pstr = pg_any_to_server(*str, strlen(*str), encoding);
512  if (pstr == *str)
513  return; /* no conversion happened */
514 
515  /* need it malloc'd not palloc'd */
516  mstr = strdup(pstr);
517  if (mstr == NULL)
518  ereport(ERROR,
519  (errcode(ERRCODE_OUT_OF_MEMORY),
520  errmsg("out of memory")));
521 
522  /* replace old string */
523  free(*str);
524  *str = mstr;
525 
526  pfree(pstr);
527 }
const char * str
#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 455 of file pg_locale.c.

456 {
457  free(s->decimal_point);
458  free(s->thousands_sep);
459  free(s->grouping);
460  free(s->int_curr_symbol);
461  free(s->currency_symbol);
462  free(s->mon_decimal_point);
463  free(s->mon_thousands_sep);
464  free(s->mon_grouping);
465  free(s->positive_sign);
466  free(s->negative_sign);
467 }

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1518 of file pg_locale.c.

1519 {
1520  char *collversion = NULL;
1521 
1522  /*
1523  * The only two supported locales (C and C.UTF-8) are both based on memcmp
1524  * and are not expected to change, but track the version anyway.
1525  *
1526  * Note that the character semantics may change for some locales, but the
1527  * collation version only tracks changes to sort order.
1528  */
1529  if (collprovider == COLLPROVIDER_BUILTIN)
1530  {
1531  if (strcmp(collcollate, "C") == 0)
1532  return "1";
1533  else if (strcmp(collcollate, "C.UTF-8") == 0)
1534  return "1";
1535  else
1536  ereport(ERROR,
1537  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1538  errmsg("invalid locale name \"%s\" for builtin provider",
1539  collcollate)));
1540  }
1541 
1542 #ifdef USE_ICU
1543  if (collprovider == COLLPROVIDER_ICU)
1544  {
1545  UCollator *collator;
1546  UVersionInfo versioninfo;
1547  char buf[U_MAX_VERSION_STRING_LENGTH];
1548 
1549  collator = pg_ucol_open(collcollate);
1550 
1551  ucol_getVersion(collator, versioninfo);
1552  ucol_close(collator);
1553 
1554  u_versionToString(versioninfo, buf);
1555  collversion = pstrdup(buf);
1556  }
1557  else
1558 #endif
1559  if (collprovider == COLLPROVIDER_LIBC &&
1560  pg_strcasecmp("C", collcollate) != 0 &&
1561  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1562  pg_strcasecmp("POSIX", collcollate) != 0)
1563  {
1564 #if defined(__GLIBC__)
1565  /* Use the glibc version because we don't have anything better. */
1566  collversion = pstrdup(gnu_get_libc_version());
1567 #elif defined(LC_VERSION_MASK)
1568  locale_t loc;
1569 
1570  /* Look up FreeBSD collation version. */
1571  loc = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1572  if (loc)
1573  {
1574  collversion =
1575  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1576  freelocale(loc);
1577  }
1578  else
1579  ereport(ERROR,
1580  (errmsg("could not load locale \"%s\"", collcollate)));
1581 #elif defined(WIN32)
1582  /*
1583  * If we are targeting Windows Vista and above, we can ask for a name
1584  * given a collation name (earlier versions required a location code
1585  * that we don't have).
1586  */
1587  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1588  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1589 
1590  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1591  LOCALE_NAME_MAX_LENGTH);
1592  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1593  {
1594  /*
1595  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1596  * locale name like "English_United States.1252". Until those
1597  * values can be prevented from entering the system, or 100%
1598  * reliably converted to the more useful tag format, tolerate the
1599  * resulting error and report that we have no version data.
1600  */
1601  if (GetLastError() == ERROR_INVALID_PARAMETER)
1602  return NULL;
1603 
1604  ereport(ERROR,
1605  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1606  collcollate,
1607  GetLastError())));
1608  }
1609  collversion = psprintf("%lu.%lu,%lu.%lu",
1610  (version.dwNLSVersion >> 8) & 0xFFFF,
1611  version.dwNLSVersion & 0xFF,
1612  (version.dwDefinedVersion >> 8) & 0xFFFF,
1613  version.dwDefinedVersion & 0xFF);
1614 #endif
1615  }
1616 
1617  return collversion;
1618 }
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 1897 of file pg_locale.c.

1898 {
1899 #ifdef USE_ICU
1900  UErrorCode status;
1901  char *langtag;
1902  size_t buflen = 32; /* arbitrary starting buffer size */
1903  const bool strict = true;
1904 
1905  /*
1906  * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
1907  * RFC5646 section 4.4). Additionally, in older ICU versions,
1908  * uloc_toLanguageTag() doesn't always return the ultimate length on the
1909  * first call, necessitating a loop.
1910  */
1911  langtag = palloc(buflen);
1912  while (true)
1913  {
1914  status = U_ZERO_ERROR;
1915  uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
1916 
1917  /* try again if the buffer is not large enough */
1918  if ((status == U_BUFFER_OVERFLOW_ERROR ||
1919  status == U_STRING_NOT_TERMINATED_WARNING) &&
1920  buflen < MaxAllocSize)
1921  {
1922  buflen = Min(buflen * 2, MaxAllocSize);
1923  langtag = repalloc(langtag, buflen);
1924  continue;
1925  }
1926 
1927  break;
1928  }
1929 
1930  if (U_FAILURE(status))
1931  {
1932  pfree(langtag);
1933 
1934  if (elevel > 0)
1935  ereport(elevel,
1936  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1937  errmsg("could not convert locale name \"%s\" to language tag: %s",
1938  loc_str, u_errorName(status))));
1939  return NULL;
1940  }
1941 
1942  return langtag;
1943 #else /* not USE_ICU */
1944  ereport(ERROR,
1945  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1946  errmsg("ICU is not supported in this build")));
1947  return NULL; /* keep compiler quiet */
1948 #endif /* not USE_ICU */
1949 }
#define Min(x, y)
Definition: c.h:995
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 1955 of file pg_locale.c.

1956 {
1957 #ifdef USE_ICU
1958  UCollator *collator;
1959  UErrorCode status;
1960  char lang[ULOC_LANG_CAPACITY];
1961  bool found = false;
1962  int elevel = icu_validation_level;
1963 
1964  /* no validation */
1965  if (elevel < 0)
1966  return;
1967 
1968  /* downgrade to WARNING during pg_upgrade */
1969  if (IsBinaryUpgrade && elevel > WARNING)
1970  elevel = WARNING;
1971 
1972  /* validate that we can extract the language */
1973  status = U_ZERO_ERROR;
1974  uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
1975  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
1976  {
1977  ereport(elevel,
1978  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1979  errmsg("could not get language from ICU locale \"%s\": %s",
1980  loc_str, u_errorName(status)),
1981  errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
1982  "icu_validation_level", "disabled")));
1983  return;
1984  }
1985 
1986  /* check for special language name */
1987  if (strcmp(lang, "") == 0 ||
1988  strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
1989  found = true;
1990 
1991  /* search for matching language within ICU */
1992  for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
1993  {
1994  const char *otherloc = uloc_getAvailable(i);
1995  char otherlang[ULOC_LANG_CAPACITY];
1996 
1997  status = U_ZERO_ERROR;
1998  uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
1999  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2000  continue;
2001 
2002  if (strcmp(lang, otherlang) == 0)
2003  found = true;
2004  }
2005 
2006  if (!found)
2007  ereport(elevel,
2008  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2009  errmsg("ICU locale \"%s\" has unknown language \"%s\"",
2010  loc_str, lang),
2011  errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
2012  "icu_validation_level", "disabled")));
2013 
2014  /* check that it can be opened */
2015  collator = pg_ucol_open(loc_str);
2016  ucol_close(collator);
2017 #else /* not USE_ICU */
2018  /* could get here if a collation was created by a build with ICU */
2019  ereport(ERROR,
2020  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2021  errmsg("ICU is not supported in this build")));
2022 #endif /* not USE_ICU */
2023 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
bool IsBinaryUpgrade
Definition: globals.c:120
int icu_validation_level
Definition: pg_locale.c:124

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

1261 {
1262  HeapTuple tup;
1263  Form_pg_database dbform;
1264  Datum datum;
1265 
1266  /* Fetch our pg_database row normally, via syscache */
1267  tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
1268  if (!HeapTupleIsValid(tup))
1269  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1270  dbform = (Form_pg_database) GETSTRUCT(tup);
1271 
1272  if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
1273  {
1274  char *datlocale;
1275 
1276  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
1277  datlocale = TextDatumGetCString(datum);
1278 
1279  builtin_validate_locale(dbform->encoding, datlocale);
1280 
1282  default_locale.ctype_is_c = (strcmp(datlocale, "C") == 0);
1283 
1286  }
1287  else if (dbform->datlocprovider == COLLPROVIDER_ICU)
1288  {
1289 #ifdef USE_ICU
1290  char *datlocale;
1291  char *icurules;
1292  bool isnull;
1293 
1294  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
1295  datlocale = TextDatumGetCString(datum);
1296 
1297  default_locale.collate_is_c = false;
1298  default_locale.ctype_is_c = false;
1299 
1300  datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull);
1301  if (!isnull)
1302  icurules = TextDatumGetCString(datum);
1303  else
1304  icurules = NULL;
1305 
1307  default_locale.info.icu.ucol = make_icu_collator(datlocale, icurules);
1308 #else
1309  /* could get here if a collation was created by a build with ICU */
1310  ereport(ERROR,
1311  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1312  errmsg("ICU is not supported in this build")));
1313 #endif
1314  }
1315  else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
1316  {
1317  const char *datcollate;
1318  const char *datctype;
1319 
1320  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datcollate);
1321  datcollate = TextDatumGetCString(datum);
1322  datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
1323  datctype = TextDatumGetCString(datum);
1324 
1325  default_locale.collate_is_c = (strcmp(datcollate, "C") == 0) ||
1326  (strcmp(datcollate, "POSIX") == 0);
1327  default_locale.ctype_is_c = (strcmp(datctype, "C") == 0) ||
1328  (strcmp(datctype, "POSIX") == 0);
1329 
1330  default_locale.info.lt = make_libc_collator(datcollate, datctype);
1331  }
1332  else
1333  /* shouldn't happen */
1334  PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
1335 
1336 
1337  default_locale.provider = dbform->datlocprovider;
1338 
1339  /*
1340  * Default locale is currently always deterministic. Nondeterministic
1341  * locales currently don't support pattern matching, which would break a
1342  * lot of things if applied globally.
1343  */
1345 
1346  ReleaseSysCache(tup);
1347 }
#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
static struct pg_locale_struct default_locale
Definition: pg_locale.c:141
locale_t make_libc_collator(const char *collate, const char *ctype)
#define PGLOCALE_SUPPORT_ERROR(provider)
Definition: pg_locale.c:81
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:1859
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
locale_t lt
Definition: pg_locale.h:91
const char * locale
Definition: pg_locale.h:89
bool deterministic
Definition: pg_locale.h:82
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:596
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:627

References 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, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, pg_locale_struct::locale, pg_locale_struct::lt, make_libc_collator(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), PGLOCALE_SUPPORT_ERROR, 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 1226 of file pg_locale.c.

1227 {
1228  collation_cache_entry *cache_entry;
1229  bool found;
1230 
1231  Assert(OidIsValid(collation));
1232  Assert(collation != DEFAULT_COLLATION_OID);
1233 
1234  if (CollationCache == NULL)
1235  {
1237  "collation cache",
1239  CollationCache = collation_cache_create(CollationCacheContext,
1240  16, NULL);
1241  }
1242 
1243  cache_entry = collation_cache_insert(CollationCache, collation, &found);
1244  if (!found)
1245  {
1246  /*
1247  * Make sure cache entry is marked invalid, in case we fail before
1248  * setting things.
1249  */
1250  cache_entry->locale = 0;
1251  }
1252 
1253  return cache_entry;
1254 }
#define Assert(condition)
Definition: c.h:849
#define OidIsValid(objectId)
Definition: c.h:766
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static MemoryContext CollationCacheContext
Definition: pg_locale.c:172
static collation_cache_hash * CollationCache
Definition: pg_locale.c:173
Definition: pg_locale.c:150
pg_locale_t locale
Definition: pg_locale.c:152

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

Referenced by pg_newlocale_from_collation().

◆ make_libc_collator()

locale_t make_libc_collator ( const char *  collate,
const char *  ctype 
)

Definition at line 53 of file pg_locale_libc.c.

54 {
55  locale_t loc = 0;
56 
57  if (strcmp(collate, ctype) == 0)
58  {
59  if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0)
60  {
61  /* Normal case where they're the same */
62  errno = 0;
63 #ifndef WIN32
64  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collate,
65  NULL);
66 #else
67  loc = _create_locale(LC_ALL, collate);
68 #endif
69  if (!loc)
70  report_newlocale_failure(collate);
71  }
72  }
73  else
74  {
75 #ifndef WIN32
76  /* We need two newlocale() steps */
77  locale_t loc1 = 0;
78 
79  if (strcmp(collate, "C") != 0 && strcmp(collate, "POSIX") != 0)
80  {
81  errno = 0;
82  loc1 = newlocale(LC_COLLATE_MASK, collate, NULL);
83  if (!loc1)
84  report_newlocale_failure(collate);
85  }
86 
87  if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0)
88  {
89  errno = 0;
90  loc = newlocale(LC_CTYPE_MASK, ctype, loc1);
91  if (!loc)
92  {
93  if (loc1)
94  freelocale(loc1);
96  }
97  }
98  else
99  loc = loc1;
100 #else
101 
102  /*
103  * XXX The _create_locale() API doesn't appear to support this. Could
104  * perhaps be worked around by changing pg_locale_t to contain two
105  * separate fields.
106  */
107  ereport(ERROR,
108  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
109  errmsg("collations with different collate and ctype values are not supported on this platform")));
110 #endif
111  }
112 
113  return loc;
114 }
static void report_newlocale_failure(const char *localename)

References ereport, errcode(), errmsg(), ERROR, locale_t, and report_newlocale_failure().

Referenced by init_database_collation(), and pg_newlocale_from_collation().

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1358 of file pg_locale.c.

1359 {
1360  collation_cache_entry *cache_entry;
1361 
1362  if (collid == DEFAULT_COLLATION_OID)
1363  return &default_locale;
1364 
1365  if (!OidIsValid(collid))
1366  elog(ERROR, "cache lookup failed for collation %u", collid);
1367 
1370 
1371  cache_entry = lookup_collation_cache(collid);
1372 
1373  if (cache_entry->locale == 0)
1374  {
1375  /* We haven't computed this yet in this session, so do it */
1376  HeapTuple tp;
1377  Form_pg_collation collform;
1378  struct pg_locale_struct result;
1379  pg_locale_t resultp;
1380  Datum datum;
1381  bool isnull;
1382 
1383  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1384  if (!HeapTupleIsValid(tp))
1385  elog(ERROR, "cache lookup failed for collation %u", collid);
1386  collform = (Form_pg_collation) GETSTRUCT(tp);
1387 
1388  /* We'll fill in the result struct locally before allocating memory */
1389  memset(&result, 0, sizeof(result));
1390  result.provider = collform->collprovider;
1391  result.deterministic = collform->collisdeterministic;
1392 
1393  if (collform->collprovider == COLLPROVIDER_BUILTIN)
1394  {
1395  const char *locstr;
1396 
1397  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1398  locstr = TextDatumGetCString(datum);
1399 
1400  result.collate_is_c = true;
1401  result.ctype_is_c = (strcmp(locstr, "C") == 0);
1402 
1404 
1405  result.info.builtin.locale = MemoryContextStrdup(TopMemoryContext,
1406  locstr);
1407  }
1408  else if (collform->collprovider == COLLPROVIDER_ICU)
1409  {
1410 #ifdef USE_ICU
1411  const char *iculocstr;
1412  const char *icurules;
1413 
1414  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1415  iculocstr = TextDatumGetCString(datum);
1416 
1417  result.collate_is_c = false;
1418  result.ctype_is_c = false;
1419 
1420  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1421  if (!isnull)
1422  icurules = TextDatumGetCString(datum);
1423  else
1424  icurules = NULL;
1425 
1426  result.info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1427  result.info.icu.ucol = make_icu_collator(iculocstr, icurules);
1428 #else
1429  /* could get here if a collation was created by a build with ICU */
1430  ereport(ERROR,
1431  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1432  errmsg("ICU is not supported in this build")));
1433 #endif
1434  }
1435  else if (collform->collprovider == COLLPROVIDER_LIBC)
1436  {
1437  const char *collcollate;
1438  const char *collctype;
1439 
1440  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1441  collcollate = TextDatumGetCString(datum);
1442  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1443  collctype = TextDatumGetCString(datum);
1444 
1445  result.collate_is_c = (strcmp(collcollate, "C") == 0) ||
1446  (strcmp(collcollate, "POSIX") == 0);
1447  result.ctype_is_c = (strcmp(collctype, "C") == 0) ||
1448  (strcmp(collctype, "POSIX") == 0);
1449 
1450  result.info.lt = make_libc_collator(collcollate, collctype);
1451  }
1452  else
1453  /* shouldn't happen */
1454  PGLOCALE_SUPPORT_ERROR(collform->collprovider);
1455 
1456  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1457  &isnull);
1458  if (!isnull)
1459  {
1460  char *actual_versionstr;
1461  char *collversionstr;
1462 
1463  collversionstr = TextDatumGetCString(datum);
1464 
1465  if (collform->collprovider == COLLPROVIDER_LIBC)
1466  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1467  else
1468  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1469 
1470  actual_versionstr = get_collation_actual_version(collform->collprovider,
1471  TextDatumGetCString(datum));
1472  if (!actual_versionstr)
1473  {
1474  /*
1475  * This could happen when specifying a version in CREATE
1476  * COLLATION but the provider does not support versioning, or
1477  * manually creating a mess in the catalogs.
1478  */
1479  ereport(ERROR,
1480  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1481  NameStr(collform->collname))));
1482  }
1483 
1484  if (strcmp(actual_versionstr, collversionstr) != 0)
1485  ereport(WARNING,
1486  (errmsg("collation \"%s\" has version mismatch",
1487  NameStr(collform->collname)),
1488  errdetail("The collation in the database was created using version %s, "
1489  "but the operating system provides version %s.",
1490  collversionstr, actual_versionstr),
1491  errhint("Rebuild all objects affected by this collation and run "
1492  "ALTER COLLATION %s REFRESH VERSION, "
1493  "or build PostgreSQL with the right library version.",
1494  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1495  NameStr(collform->collname)))));
1496  }
1497 
1498  ReleaseSysCache(tp);
1499 
1500  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1501  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1502  *resultp = result;
1503 
1504  cache_entry->locale = resultp;
1505  }
1506 
1508  last_collation_cache_locale = cache_entry->locale;
1509 
1510  return cache_entry->locale;
1511 }
#define NameStr(name)
Definition: c.h:737
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1203
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
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:180
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1518
static collation_cache_entry * lookup_collation_cache(Oid collation)
Definition: pg_locale.c:1226
static Oid last_collation_cache_oid
Definition: pg_locale.c:179
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, errcode(), 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, pg_locale_struct::locale, lookup_collation_cache(), pg_locale_struct::lt, make_libc_collator(), MemoryContextAlloc(), MemoryContextStrdup(), NameStr, ObjectIdGetDatum(), OidIsValid, PGLOCALE_SUPPORT_ERROR, 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 201 of file pg_locale.c.

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

1627 {
1628  int result;
1629 
1630  if (locale->provider == COLLPROVIDER_LIBC)
1631  result = strncoll_libc(arg1, -1, arg2, -1, locale);
1632 #ifdef USE_ICU
1633  else if (locale->provider == COLLPROVIDER_ICU)
1634  result = strncoll_icu(arg1, -1, arg2, -1, locale);
1635 #endif
1636  else
1637  /* shouldn't happen */
1638  PGLOCALE_SUPPORT_ERROR(locale->provider);
1639 
1640  return result;
1641 }
int strncoll_libc(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale)

References locale, PGLOCALE_SUPPORT_ERROR, and strncoll_libc().

Referenced by varstrfastcmp_locale().

◆ pg_strncoll()

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

Definition at line 1658 of file pg_locale.c.

1660 {
1661  int result;
1662 
1663  if (locale->provider == COLLPROVIDER_LIBC)
1664  result = strncoll_libc(arg1, len1, arg2, len2, locale);
1665 #ifdef USE_ICU
1666  else if (locale->provider == COLLPROVIDER_ICU)
1667  result = strncoll_icu(arg1, len1, arg2, len2, locale);
1668 #endif
1669  else
1670  /* shouldn't happen */
1671  PGLOCALE_SUPPORT_ERROR(locale->provider);
1672 
1673  return result;
1674 }

References locale, PGLOCALE_SUPPORT_ERROR, and strncoll_libc().

Referenced by varstr_cmp().

◆ pg_strnxfrm()

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

Definition at line 1751 of file pg_locale.c.

1753 {
1754  size_t result = 0; /* keep compiler quiet */
1755 
1756  if (locale->provider == COLLPROVIDER_LIBC)
1757  result = strnxfrm_libc(dest, destsize, src, srclen, locale);
1758 #ifdef USE_ICU
1759  else if (locale->provider == COLLPROVIDER_ICU)
1760  result = strnxfrm_icu(dest, destsize, src, srclen, locale);
1761 #endif
1762  else
1763  /* shouldn't happen */
1764  PGLOCALE_SUPPORT_ERROR(locale->provider);
1765 
1766  return result;
1767 }
size_t strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)

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

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

◆ pg_strnxfrm_prefix()

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

Definition at line 1818 of file pg_locale.c.

1820 {
1821  size_t result = 0; /* keep compiler quiet */
1822 
1823 #ifdef USE_ICU
1824  if (locale->provider == COLLPROVIDER_ICU)
1825  result = strnxfrm_prefix_icu(dest, destsize, src, -1, locale);
1826  else
1827 #endif
1828  PGLOCALE_SUPPORT_ERROR(locale->provider);
1829 
1830  return result;
1831 }

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by pg_strxfrm_prefix().

◆ pg_strxfrm()

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

Definition at line 1714 of file pg_locale.c.

1715 {
1716  size_t result = 0; /* keep compiler quiet */
1717 
1718  if (locale->provider == COLLPROVIDER_LIBC)
1719  result = strnxfrm_libc(dest, destsize, src, -1, locale);
1720 #ifdef USE_ICU
1721  else if (locale->provider == COLLPROVIDER_ICU)
1722  result = strnxfrm_icu(dest, destsize, src, -1, locale);
1723 #endif
1724  else
1725  /* shouldn't happen */
1726  PGLOCALE_SUPPORT_ERROR(locale->provider);
1727 
1728  return result;
1729 }

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

Referenced by convert_string_datum(), and varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 1691 of file pg_locale.c.

1692 {
1693  if (locale->provider == COLLPROVIDER_LIBC)
1694 #ifdef TRUST_STRXFRM
1695  return true;
1696 #else
1697  return false;
1698 #endif
1699  else if (locale->provider == COLLPROVIDER_ICU)
1700  return true;
1701  else
1702  /* shouldn't happen */
1703  PGLOCALE_SUPPORT_ERROR(locale->provider);
1704 
1705  return false; /* keep compiler quiet */
1706 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_sortsupport().

◆ pg_strxfrm_prefix()

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

Definition at line 1793 of file pg_locale.c.

1795 {
1796  return pg_strnxfrm_prefix(dest, destsize, src, -1, locale);
1797 }
size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
Definition: pg_locale.c:1818

References generate_unaccent_rules::dest, locale, and pg_strnxfrm_prefix().

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_prefix_enabled()

bool pg_strxfrm_prefix_enabled ( pg_locale_t  locale)

Definition at line 1774 of file pg_locale.c.

1775 {
1776  if (locale->provider == COLLPROVIDER_LIBC)
1777  return false;
1778  else if (locale->provider == COLLPROVIDER_ICU)
1779  return true;
1780  else
1781  /* shouldn't happen */
1782  PGLOCALE_SUPPORT_ERROR(locale->provider);
1783 
1784  return false; /* keep compiler quiet */
1785 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 535 of file pg_locale.c.

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

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

◆ strncoll_libc()

int strncoll_libc ( const char *  arg1,
ssize_t  len1,
const char *  arg2,
ssize_t  len2,
pg_locale_t  locale 
)

Definition at line 124 of file pg_locale_libc.c.

126 {
127  char sbuf[TEXTBUFLEN];
128  char *buf = sbuf;
129  size_t bufsize1 = (len1 == -1) ? 0 : len1 + 1;
130  size_t bufsize2 = (len2 == -1) ? 0 : len2 + 1;
131  const char *arg1n;
132  const char *arg2n;
133  int result;
134 
135  Assert(locale->provider == COLLPROVIDER_LIBC);
136 
137 #ifdef WIN32
138  /* check for this case before doing the work for nul-termination */
139  if (GetDatabaseEncoding() == PG_UTF8)
140  return strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
141 #endif /* WIN32 */
142 
143  if (bufsize1 + bufsize2 > TEXTBUFLEN)
144  buf = palloc(bufsize1 + bufsize2);
145 
146  /* nul-terminate arguments if necessary */
147  if (len1 == -1)
148  {
149  arg1n = arg1;
150  }
151  else
152  {
153  char *buf1 = buf;
154 
155  memcpy(buf1, arg1, len1);
156  buf1[len1] = '\0';
157  arg1n = buf1;
158  }
159 
160  if (len2 == -1)
161  {
162  arg2n = arg2;
163  }
164  else
165  {
166  char *buf2 = buf + bufsize1;
167 
168  memcpy(buf2, arg2, len2);
169  buf2[len2] = '\0';
170  arg2n = buf2;
171  }
172 
173  result = strcoll_l(arg1n, arg2n, locale->info.lt);
174 
175  if (buf != sbuf)
176  pfree(buf);
177 
178  return result;
179 }
#define TEXTBUFLEN
#define strcoll_l
Definition: win32_port.h:465

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

Referenced by pg_strcoll(), and pg_strncoll().

◆ strnxfrm_libc()

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

Definition at line 189 of file pg_locale_libc.c.

191 {
192  char sbuf[TEXTBUFLEN];
193  char *buf = sbuf;
194  size_t bufsize = srclen + 1;
195  size_t result;
196 
197  Assert(locale->provider == COLLPROVIDER_LIBC);
198 
199  if (srclen == -1)
200  return strxfrm_l(dest, src, destsize, locale->info.lt);
201 
202  if (bufsize > TEXTBUFLEN)
203  buf = palloc(bufsize);
204 
205  /* nul-terminate argument */
206  memcpy(buf, src, srclen);
207  buf[srclen] = '\0';
208 
209  result = strxfrm_l(dest, buf, destsize, locale->info.lt);
210 
211  if (buf != sbuf)
212  pfree(buf);
213 
214  /* if dest is defined, it should be nul-terminated */
215  Assert(result >= destsize || dest[result] == '\0');
216 
217  return result;
218 }
#define bufsize
Definition: indent_globs.h:36
#define strxfrm_l
Definition: win32_port.h:466

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

Referenced by pg_strnxfrm(), and pg_strxfrm().

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 474 of file pg_locale.c.

475 {
476  if (s->decimal_point == NULL)
477  return false;
478  if (s->thousands_sep == NULL)
479  return false;
480  if (s->grouping == NULL)
481  return false;
482  if (s->int_curr_symbol == NULL)
483  return false;
484  if (s->currency_symbol == NULL)
485  return false;
486  if (s->mon_decimal_point == NULL)
487  return false;
488  if (s->mon_thousands_sep == NULL)
489  return false;
490  if (s->mon_grouping == NULL)
491  return false;
492  if (s->positive_sign == NULL)
493  return false;
494  if (s->negative_sign == NULL)
495  return false;
496  return true;
497 }

Referenced by PGLC_localeconv().

Variable Documentation

◆ CollationCache

collation_cache_hash* CollationCache = NULL
static

Definition at line 173 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CollationCacheContext

MemoryContext CollationCacheContext = NULL
static

Definition at line 172 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 145 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 144 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 139 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 124 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 180 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 179 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ locale_messages

char* locale_messages

Definition at line 119 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 120 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 121 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 122 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 133 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 135 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 134 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 136 of file pg_locale.c.

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