Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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/guc_hooks.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/relcache.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

pg_locale_t create_pg_locale_builtin (Oid collid, MemoryContext context)
 
char * get_collation_actual_version_builtin (const char *collcollate)
 
pg_locale_t create_pg_locale_icu (Oid collid, MemoryContext context)
 
pg_locale_t create_pg_locale_libc (Oid collid, MemoryContext context)
 
char * get_collation_actual_version_libc (const char *collcollate)
 
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 pg_locale_t create_pg_locale (Oid collid, MemoryContext context)
 
void init_database_collation (void)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
size_t pg_strlower (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t pg_strtitle (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t pg_strupper (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t pg_strfold (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
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)
 
bool char_is_cased (char ch, pg_locale_t locale)
 
bool char_tolower_enabled (pg_locale_t locale)
 
char char_tolower (unsigned char ch, 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 pg_locale_t default_locale = NULL
 
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 65 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 56 of file pg_locale.c.

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 132 of file pg_locale.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 133 of file pg_locale.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   collation_cache_entry

Definition at line 124 of file pg_locale.c.

◆ SH_EQUAL

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

Definition at line 128 of file pg_locale.c.

◆ SH_GET_HASH

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

Definition at line 129 of file pg_locale.c.

◆ SH_HASH_KEY

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

Definition at line 127 of file pg_locale.c.

◆ SH_KEY

#define SH_KEY   collid

Definition at line 126 of file pg_locale.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   Oid

Definition at line 125 of file pg_locale.c.

◆ SH_PREFIX

#define SH_PREFIX   collation_cache

Definition at line 123 of file pg_locale.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 130 of file pg_locale.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

Definition at line 131 of file pg_locale.c.

◆ TEXTBUFLEN

#define TEXTBUFLEN   1024

Definition at line 63 of file pg_locale.c.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 402 of file pg_locale.c.

403{
404 /*
405 * LC_MESSAGES category does not exist everywhere, but accept it anyway.
406 * We ignore failure, as per comment above.
407 */
408#ifdef LC_MESSAGES
409 (void) pg_perm_setlocale(LC_MESSAGES, newval);
410#endif
411}
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:165

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 339 of file pg_locale.c.

340{
342}
static bool CurrentLocaleConvValid
Definition: pg_locale.c:108

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 351 of file pg_locale.c.

352{
354}

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 363 of file pg_locale.c.

364{
365 CurrentLCTimeValid = false;
366}
static bool CurrentLCTimeValid
Definition: pg_locale.c:109

References CurrentLCTimeValid.

◆ builtin_locale_encoding()

int builtin_locale_encoding ( const char *  locale)

Definition at line 1438 of file pg_locale.c.

1439{
1440 if (strcmp(locale, "C") == 0)
1441 return -1;
1442 else if (strcmp(locale, "C.UTF-8") == 0)
1443 return PG_UTF8;
1444 else if (strcmp(locale, "PG_UNICODE_FAST") == 0)
1445 return PG_UTF8;
1446
1447
1448 ereport(ERROR,
1449 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1450 errmsg("invalid locale name \"%s\" for builtin provider",
1451 locale)));
1452
1453 return 0; /* keep compiler quiet */
1454}
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
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 1462 of file pg_locale.c.

1463{
1464 const char *canonical_name = NULL;
1465 int required_encoding;
1466
1467 if (strcmp(locale, "C") == 0)
1468 canonical_name = "C";
1469 else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0)
1470 canonical_name = "C.UTF-8";
1471 else if (strcmp(locale, "PG_UNICODE_FAST") == 0)
1472 canonical_name = "PG_UNICODE_FAST";
1473
1474 if (!canonical_name)
1475 ereport(ERROR,
1476 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1477 errmsg("invalid locale name \"%s\" for builtin provider",
1478 locale)));
1479
1480 required_encoding = builtin_locale_encoding(canonical_name);
1481 if (required_encoding >= 0 && encoding != required_encoding)
1482 ereport(ERROR,
1483 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1484 errmsg("encoding \"%s\" does not match locale \"%s\"",
1486
1487 return canonical_name;
1488}
int32 encoding
Definition: pg_database.h:41
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:1438
#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 create_pg_locale_builtin(), createdb(), and DefineCollation().

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 695 of file pg_locale.c.

696{
697 char buf[(2 * 7 + 2 * 12) * MAX_L10N_DATA];
698 char *bufptr;
699 time_t timenow;
700 struct tm *timeinfo;
701 struct tm timeinfobuf;
702 bool strftimefail = false;
703 int encoding;
704 int i;
706
707 /* did we do this already? */
709 return;
710
711 elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
712
713 errno = ENOENT;
714#ifdef WIN32
715 locale = _create_locale(LC_ALL, locale_time);
716 if (locale == (locale_t) 0)
717 _dosmaperr(GetLastError());
718#else
719 locale = newlocale(LC_ALL_MASK, locale_time, (locale_t) 0);
720#endif
721 if (!locale)
723
724 /* We use times close to current time as data for strftime(). */
725 timenow = time(NULL);
726 timeinfo = gmtime_r(&timenow, &timeinfobuf);
727
728 /* Store the strftime results in MAX_L10N_DATA-sized portions of buf[] */
729 bufptr = buf;
730
731 /*
732 * MAX_L10N_DATA is sufficient buffer space for every known locale, and
733 * POSIX defines no strftime() errors. (Buffer space exhaustion is not an
734 * error.) An implementation might report errors (e.g. ENOMEM) by
735 * returning 0 (or, less plausibly, a negative value) and setting errno.
736 * Report errno just in case the implementation did that, but clear it in
737 * advance of the calls so we don't emit a stale, unrelated errno.
738 */
739 errno = 0;
740
741 /* localized days */
742 for (i = 0; i < 7; i++)
743 {
744 timeinfo->tm_wday = i;
745 if (strftime_l(bufptr, MAX_L10N_DATA, "%a", timeinfo, locale) <= 0)
746 strftimefail = true;
747 bufptr += MAX_L10N_DATA;
748 if (strftime_l(bufptr, MAX_L10N_DATA, "%A", timeinfo, locale) <= 0)
749 strftimefail = true;
750 bufptr += MAX_L10N_DATA;
751 }
752
753 /* localized months */
754 for (i = 0; i < 12; i++)
755 {
756 timeinfo->tm_mon = i;
757 timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
758 if (strftime_l(bufptr, MAX_L10N_DATA, "%b", timeinfo, locale) <= 0)
759 strftimefail = true;
760 bufptr += MAX_L10N_DATA;
761 if (strftime_l(bufptr, MAX_L10N_DATA, "%B", timeinfo, locale) <= 0)
762 strftimefail = true;
763 bufptr += MAX_L10N_DATA;
764 }
765
766#ifdef WIN32
767 _free_locale(locale);
768#else
769 freelocale(locale);
770#endif
771
772 /*
773 * At this point we've done our best to clean up, and can throw errors, or
774 * call functions that might throw errors, with a clean conscience.
775 */
776 if (strftimefail)
777 elog(ERROR, "strftime_l() failed");
778
779#ifndef WIN32
780
781 /*
782 * As in PGLC_localeconv(), we must convert strftime()'s output from the
783 * encoding implied by LC_TIME to the database encoding. If we can't
784 * identify the LC_TIME encoding, just perform encoding validation.
785 */
787 if (encoding < 0)
789
790#else
791
792 /*
793 * On Windows, strftime_win32() always returns UTF8 data, so convert from
794 * that if necessary.
795 */
797
798#endif /* WIN32 */
799
800 bufptr = buf;
801
802 /* localized days */
803 for (i = 0; i < 7; i++)
804 {
806 bufptr += MAX_L10N_DATA;
808 bufptr += MAX_L10N_DATA;
809 }
810 localized_abbrev_days[7] = NULL;
811 localized_full_days[7] = NULL;
812
813 /* localized months */
814 for (i = 0; i < 12; i++)
815 {
817 bufptr += MAX_L10N_DATA;
819 bufptr += MAX_L10N_DATA;
820 }
821 localized_abbrev_months[12] = NULL;
822 localized_full_months[12] = NULL;
823
824 CurrentLCTimeValid = true;
825}
#define DEBUG3
Definition: elog.h:28
#define elog(elevel,...)
Definition: elog.h:226
int i
Definition: isn.c:77
static struct pg_tm tm
Definition: localtime.c:104
char * localized_full_months[12+1]
Definition: pg_locale.c:100
char * locale_time
Definition: pg_locale.c:86
static void cache_single_string(char **dst, const char *src, int encoding)
Definition: pg_locale.c:672
#define MAX_L10N_DATA
Definition: pg_locale.c:65
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:99
char * localized_full_days[7+1]
Definition: pg_locale.c:98
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:97
void report_newlocale_failure(const char *localename)
static char * buf
Definition: pg_test_fsync.c:72
@ 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 locale_t
Definition: win32_port.h:432
void _dosmaperr(unsigned long)
Definition: win32error.c:177

References _dosmaperr(), buf, cache_single_string(), CurrentLCTimeValid, DEBUG3, elog, encoding, ERROR, i, locale, locale_t, locale_time, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, MAX_L10N_DATA, pg_get_encoding_from_locale(), PG_SQL_ASCII, PG_UTF8, report_newlocale_failure(), 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 672 of file pg_locale.c.

673{
674 char *ptr;
675 char *olddst;
676
677 /* Convert the string to the database encoding, or validate it's OK */
678 ptr = pg_any_to_server(src, strlen(src), encoding);
679
680 /* Store the string in long-lived storage, replacing any previous value */
681 olddst = *dst;
683 if (olddst)
684 pfree(olddst);
685
686 /* Might as well clean up any palloc'd conversion result, too */
687 if (ptr != src)
688 pfree(ptr);
689}
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:677
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1746
void pfree(void *pointer)
Definition: mcxt.c:1594
MemoryContext TopMemoryContext
Definition: mcxt.c:166

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

Referenced by cache_locale_time().

◆ char_is_cased()

bool char_is_cased ( char  ch,
pg_locale_t  locale 
)

Definition at line 1406 of file pg_locale.c.

1407{
1408 return locale->ctype->char_is_cased(ch, locale);
1409}

References locale.

Referenced by pattern_char_isalpha().

◆ char_tolower()

char char_tolower ( unsigned char  ch,
pg_locale_t  locale 
)

Definition at line 1428 of file pg_locale.c.

1429{
1430 return locale->ctype->char_tolower(ch, locale);
1431}

References locale.

Referenced by SB_lower_char().

◆ char_tolower_enabled()

bool char_tolower_enabled ( pg_locale_t  locale)

Definition at line 1417 of file pg_locale.c.

1418{
1419 return (locale->ctype->char_tolower != NULL);
1420}

References locale.

Referenced by Generic_Text_IC_like().

◆ check_locale()

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

Definition at line 268 of file pg_locale.c.

269{
270 char *save;
271 char *res;
272
273 /* Don't let Windows' non-ASCII locale names in. */
274 if (!pg_is_ascii(locale))
275 {
277 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
278 errmsg("locale name \"%s\" contains non-ASCII characters",
279 locale)));
280 return false;
281 }
282
283 if (canonname)
284 *canonname = NULL; /* in case of failure */
285
286 save = setlocale(category, NULL);
287 if (!save)
288 return false; /* won't happen, we hope */
289
290 /* save may be pointing at a modifiable scratch variable, see above. */
291 save = pstrdup(save);
292
293 /* set the locale with setlocale, to see if it accepts it. */
294 res = setlocale(category, locale);
295
296 /* save canonical name if requested. */
297 if (res && canonname)
298 *canonname = pstrdup(res);
299
300 /* restore old value. */
301 if (!setlocale(category, save))
302 elog(WARNING, "failed to restore old locale \"%s\"", save);
303 pfree(save);
304
305 /* Don't let Windows' non-ASCII locale names out. */
306 if (canonname && *canonname && !pg_is_ascii(*canonname))
307 {
309 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
310 errmsg("locale name \"%s\" contains non-ASCII characters",
311 *canonname)));
312 pfree(*canonname);
313 *canonname = NULL;
314 return false;
315 }
316
317 return (res != NULL);
318}
#define WARNING
Definition: elog.h:36
char * pstrdup(const char *in)
Definition: mcxt.c:1759
bool pg_is_ascii(const char *str)
Definition: string.c:132
#define setlocale(a, b)
Definition: win32_port.h:475

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

380{
381 if (**newval == '\0')
382 {
383 if (source == PGC_S_DEFAULT)
384 return true;
385 else
386 return false;
387 }
388
389 /*
390 * LC_MESSAGES category does not exist everywhere, but accept it anyway
391 *
392 * On Windows, we can't even check the value, so accept blindly
393 */
394#if defined(LC_MESSAGES) && !defined(WIN32)
395 return check_locale(LC_MESSAGES, *newval, NULL);
396#else
397 return true;
398#endif
399}
@ PGC_S_DEFAULT
Definition: guc.h:113
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:268
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 333 of file pg_locale.c.

334{
335 return check_locale(LC_MONETARY, *newval, NULL);
336}

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 345 of file pg_locale.c.

346{
347 return check_locale(LC_NUMERIC, *newval, NULL);
348}

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 357 of file pg_locale.c.

358{
359 return check_locale(LC_TIME, *newval, NULL);
360}

References check_locale(), and newval.

◆ create_pg_locale()

static pg_locale_t create_pg_locale ( Oid  collid,
MemoryContext  context 
)
static

Definition at line 1042 of file pg_locale.c.

1043{
1044 HeapTuple tp;
1045 Form_pg_collation collform;
1046 pg_locale_t result;
1047 Datum datum;
1048 bool isnull;
1049
1050 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1051 if (!HeapTupleIsValid(tp))
1052 elog(ERROR, "cache lookup failed for collation %u", collid);
1053 collform = (Form_pg_collation) GETSTRUCT(tp);
1054
1055 if (collform->collprovider == COLLPROVIDER_BUILTIN)
1056 result = create_pg_locale_builtin(collid, context);
1057 else if (collform->collprovider == COLLPROVIDER_ICU)
1058 result = create_pg_locale_icu(collid, context);
1059 else if (collform->collprovider == COLLPROVIDER_LIBC)
1060 result = create_pg_locale_libc(collid, context);
1061 else
1062 /* shouldn't happen */
1063 PGLOCALE_SUPPORT_ERROR(collform->collprovider);
1064
1065 result->is_default = false;
1066
1067 Assert((result->collate_is_c && result->collate == NULL) ||
1068 (!result->collate_is_c && result->collate != NULL));
1069
1070 Assert((result->ctype_is_c && result->ctype == NULL) ||
1071 (!result->ctype_is_c && result->ctype != NULL));
1072
1073 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1074 &isnull);
1075 if (!isnull)
1076 {
1077 char *actual_versionstr;
1078 char *collversionstr;
1079
1080 collversionstr = TextDatumGetCString(datum);
1081
1082 if (collform->collprovider == COLLPROVIDER_LIBC)
1083 datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1084 else
1085 datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1086
1087 actual_versionstr = get_collation_actual_version(collform->collprovider,
1088 TextDatumGetCString(datum));
1089 if (!actual_versionstr)
1090 {
1091 /*
1092 * This could happen when specifying a version in CREATE COLLATION
1093 * but the provider does not support versioning, or manually
1094 * creating a mess in the catalogs.
1095 */
1096 ereport(ERROR,
1097 (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1098 NameStr(collform->collname))));
1099 }
1100
1101 if (strcmp(actual_versionstr, collversionstr) != 0)
1103 (errmsg("collation \"%s\" has version mismatch",
1104 NameStr(collform->collname)),
1105 errdetail("The collation in the database was created using version %s, "
1106 "but the operating system provides version %s.",
1107 collversionstr, actual_versionstr),
1108 errhint("Rebuild all objects affected by this collation and run "
1109 "ALTER COLLATION %s REFRESH VERSION, "
1110 "or build PostgreSQL with the right library version.",
1111 quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1112 NameStr(collform->collname)))));
1113 }
1114
1115 ReleaseSysCache(tp);
1116
1117 return result;
1118}
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:751
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1207
int errhint(const char *fmt,...)
Definition: elog.c:1321
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context)
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1217
pg_locale_t create_pg_locale_builtin(Oid collid, MemoryContext context)
#define PGLOCALE_SUPPORT_ERROR(provider)
Definition: pg_locale.c:56
pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context)
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:13114
const struct ctype_methods * ctype
Definition: pg_locale.h:157
const struct collate_methods * collate
Definition: pg_locale.h:156
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:595
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:625

References Assert(), pg_locale_struct::collate, pg_locale_struct::collate_is_c, collid, create_pg_locale_builtin(), create_pg_locale_icu(), create_pg_locale_libc(), pg_locale_struct::ctype, pg_locale_struct::ctype_is_c, elog, ereport, errdetail(), errhint(), errmsg(), ERROR, get_collation_actual_version(), get_namespace_name(), GETSTRUCT(), HeapTupleIsValid, pg_locale_struct::is_default, NameStr, ObjectIdGetDatum(), PGLOCALE_SUPPORT_ERROR, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, and WARNING.

Referenced by pg_newlocale_from_collation().

◆ create_pg_locale_builtin()

pg_locale_t create_pg_locale_builtin ( Oid  collid,
MemoryContext  context 
)

Definition at line 205 of file pg_locale_builtin.c.

206{
207 const char *locstr;
208 pg_locale_t result;
209
210 if (collid == DEFAULT_COLLATION_OID)
211 {
212 HeapTuple tp;
213 Datum datum;
214
216 if (!HeapTupleIsValid(tp))
217 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
218 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
219 Anum_pg_database_datlocale);
220 locstr = TextDatumGetCString(datum);
221 ReleaseSysCache(tp);
222 }
223 else
224 {
225 HeapTuple tp;
226 Datum datum;
227
229 if (!HeapTupleIsValid(tp))
230 elog(ERROR, "cache lookup failed for collation %u", collid);
231 datum = SysCacheGetAttrNotNull(COLLOID, tp,
232 Anum_pg_collation_colllocale);
233 locstr = TextDatumGetCString(datum);
234 ReleaseSysCache(tp);
235 }
236
238
239 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
240
241 result->builtin.locale = MemoryContextStrdup(context, locstr);
242 result->builtin.casemap_full = (strcmp(locstr, "PG_UNICODE_FAST") == 0);
243 result->deterministic = true;
244 result->collate_is_c = true;
245 result->ctype_is_c = (strcmp(locstr, "C") == 0);
246 if (!result->ctype_is_c)
247 result->ctype = &ctype_methods_builtin;
248
249 return result;
250}
Oid MyDatabaseId
Definition: globals.c:94
int GetDatabaseEncoding(void)
Definition: mbutils.c:1262
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1263
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:1462
static const struct ctype_methods ctype_methods_builtin
struct pg_locale_struct::@163::@165 builtin
const char * locale
Definition: pg_locale.h:163

References pg_locale_struct::builtin, builtin_validate_locale(), pg_locale_struct::casemap_full, pg_locale_struct::collate_is_c, collid, pg_locale_struct::ctype, pg_locale_struct::ctype_is_c, ctype_methods_builtin, pg_locale_struct::deterministic, elog, ERROR, GetDatabaseEncoding(), HeapTupleIsValid, pg_locale_struct::locale, MemoryContextAllocZero(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

Referenced by create_pg_locale(), and init_database_collation().

◆ create_pg_locale_icu()

pg_locale_t create_pg_locale_icu ( Oid  collid,
MemoryContext  context 
)

Definition at line 236 of file pg_locale_icu.c.

237{
238#ifdef USE_ICU
239 bool deterministic;
240 const char *iculocstr;
241 const char *icurules = NULL;
242 UCollator *collator;
243 pg_locale_t result;
244
245 if (collid == DEFAULT_COLLATION_OID)
246 {
247 HeapTuple tp;
248 Datum datum;
249 bool isnull;
250
252 if (!HeapTupleIsValid(tp))
253 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
254
255 /* default database collation is always deterministic */
256 deterministic = true;
257 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
258 Anum_pg_database_datlocale);
259 iculocstr = TextDatumGetCString(datum);
260 datum = SysCacheGetAttr(DATABASEOID, tp,
261 Anum_pg_database_daticurules, &isnull);
262 if (!isnull)
263 icurules = TextDatumGetCString(datum);
264
265 ReleaseSysCache(tp);
266 }
267 else
268 {
269 Form_pg_collation collform;
270 HeapTuple tp;
271 Datum datum;
272 bool isnull;
273
275 if (!HeapTupleIsValid(tp))
276 elog(ERROR, "cache lookup failed for collation %u", collid);
277 collform = (Form_pg_collation) GETSTRUCT(tp);
278 deterministic = collform->collisdeterministic;
279 datum = SysCacheGetAttrNotNull(COLLOID, tp,
280 Anum_pg_collation_colllocale);
281 iculocstr = TextDatumGetCString(datum);
282 datum = SysCacheGetAttr(COLLOID, tp,
283 Anum_pg_collation_collicurules, &isnull);
284 if (!isnull)
285 icurules = TextDatumGetCString(datum);
286
287 ReleaseSysCache(tp);
288 }
289
290 collator = make_icu_collator(iculocstr, icurules);
291
292 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
293 result->icu.locale = MemoryContextStrdup(context, iculocstr);
294 result->icu.ucol = collator;
295 result->deterministic = deterministic;
296 result->collate_is_c = false;
297 result->ctype_is_c = false;
299 result->collate = &collate_methods_icu_utf8;
300 else
301 result->collate = &collate_methods_icu;
302 result->ctype = &ctype_methods_icu;
303
304 return result;
305#else
306 /* could get here if a collation was created by a build with ICU */
308 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
309 errmsg("ICU is not supported in this build")));
310
311 return NULL;
312#endif
313}

References pg_locale_struct::collate, pg_locale_struct::collate_is_c, collid, pg_locale_struct::ctype, pg_locale_struct::ctype_is_c, pg_locale_struct::deterministic, elog, ereport, errcode(), errmsg(), ERROR, GetDatabaseEncoding(), GETSTRUCT(), HeapTupleIsValid, pg_locale_struct::locale, MemoryContextAllocZero(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), PG_UTF8, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

Referenced by create_pg_locale(), and init_database_collation().

◆ create_pg_locale_libc()

pg_locale_t create_pg_locale_libc ( Oid  collid,
MemoryContext  context 
)

Definition at line 669 of file pg_locale_libc.c.

670{
671 const char *collate;
672 const char *ctype;
673 locale_t loc;
674 pg_locale_t result;
675
676 if (collid == DEFAULT_COLLATION_OID)
677 {
678 HeapTuple tp;
679 Datum datum;
680
682 if (!HeapTupleIsValid(tp))
683 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
684 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
685 Anum_pg_database_datcollate);
686 collate = TextDatumGetCString(datum);
687 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
688 Anum_pg_database_datctype);
689 ctype = TextDatumGetCString(datum);
690
691 ReleaseSysCache(tp);
692 }
693 else
694 {
695 HeapTuple tp;
696 Datum datum;
697
699 if (!HeapTupleIsValid(tp))
700 elog(ERROR, "cache lookup failed for collation %u", collid);
701
702 datum = SysCacheGetAttrNotNull(COLLOID, tp,
703 Anum_pg_collation_collcollate);
704 collate = TextDatumGetCString(datum);
705 datum = SysCacheGetAttrNotNull(COLLOID, tp,
706 Anum_pg_collation_collctype);
707 ctype = TextDatumGetCString(datum);
708
709 ReleaseSysCache(tp);
710 }
711
712
713 loc = make_libc_collator(collate, ctype);
714
715 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
716 result->deterministic = true;
717 result->collate_is_c = (strcmp(collate, "C") == 0) ||
718 (strcmp(collate, "POSIX") == 0);
719 result->ctype_is_c = (strcmp(ctype, "C") == 0) ||
720 (strcmp(ctype, "POSIX") == 0);
721 result->lt = loc;
722 if (!result->collate_is_c)
723 {
724#ifdef WIN32
726 result->collate = &collate_methods_libc_win32_utf8;
727 else
728#endif
729 result->collate = &collate_methods_libc;
730 }
731 if (!result->ctype_is_c)
732 {
737 else
738 result->ctype = &ctype_methods_libc_sb;
739 }
740
741 return result;
742}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1547
static const struct ctype_methods ctype_methods_libc_other_mb
static const struct ctype_methods ctype_methods_libc_utf8
static locale_t make_libc_collator(const char *collate, const char *ctype)
static const struct collate_methods collate_methods_libc
static const struct ctype_methods ctype_methods_libc_sb

References pg_locale_struct::collate, pg_locale_struct::collate_is_c, collate_methods_libc, collid, pg_locale_struct::ctype, pg_locale_struct::ctype_is_c, ctype_methods_libc_other_mb, ctype_methods_libc_sb, ctype_methods_libc_utf8, pg_locale_struct::deterministic, elog, ERROR, GetDatabaseEncoding(), HeapTupleIsValid, if(), locale_t, pg_locale_struct::lt, make_libc_collator(), MemoryContextAllocZero(), MyDatabaseId, ObjectIdGetDatum(), pg_database_encoding_max_length(), PG_UTF8, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

Referenced by create_pg_locale(), and init_database_collation().

◆ db_encoding_convert()

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

Definition at line 469 of file pg_locale.c.

470{
471 char *pstr;
472 char *mstr;
473
474 /* convert the string to the database encoding */
475 pstr = pg_any_to_server(*str, strlen(*str), encoding);
476 if (pstr == *str)
477 return; /* no conversion happened */
478
479 /* need it malloc'd not palloc'd */
480 mstr = strdup(pstr);
481 if (mstr == NULL)
483 (errcode(ERRCODE_OUT_OF_MEMORY),
484 errmsg("out of memory")));
485
486 /* replace old string */
487 free(*str);
488 *str = mstr;
489
490 pfree(pstr);
491}
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 419 of file pg_locale.c.

420{
421 free(s->decimal_point);
422 free(s->thousands_sep);
423 free(s->grouping);
424 free(s->int_curr_symbol);
425 free(s->currency_symbol);
426 free(s->mon_decimal_point);
427 free(s->mon_thousands_sep);
428 free(s->mon_grouping);
429 free(s->positive_sign);
430 free(s->negative_sign);
431}

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1217 of file pg_locale.c.

1218{
1219 char *collversion = NULL;
1220
1221 if (collprovider == COLLPROVIDER_BUILTIN)
1222 collversion = get_collation_actual_version_builtin(collcollate);
1223#ifdef USE_ICU
1224 else if (collprovider == COLLPROVIDER_ICU)
1225 collversion = get_collation_actual_version_icu(collcollate);
1226#endif
1227 else if (collprovider == COLLPROVIDER_LIBC)
1228 collversion = get_collation_actual_version_libc(collcollate);
1229
1230 return collversion;
1231}
char * get_collation_actual_version_libc(const char *collcollate)
char * get_collation_actual_version_builtin(const char *collcollate)

References get_collation_actual_version_builtin(), and get_collation_actual_version_libc().

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

◆ get_collation_actual_version_builtin()

char * get_collation_actual_version_builtin ( const char *  collcollate)

Definition at line 253 of file pg_locale_builtin.c.

254{
255 /*
256 * The only two supported locales (C and C.UTF-8) are both based on memcmp
257 * and are not expected to change, but track the version anyway.
258 *
259 * Note that the character semantics may change for some locales, but the
260 * collation version only tracks changes to sort order.
261 */
262 if (strcmp(collcollate, "C") == 0)
263 return "1";
264 else if (strcmp(collcollate, "C.UTF-8") == 0)
265 return "1";
266 else if (strcmp(collcollate, "PG_UNICODE_FAST") == 0)
267 return "1";
268 else
270 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
271 errmsg("invalid locale name \"%s\" for builtin provider",
272 collcollate)));
273
274 return NULL; /* keep compiler quiet */
275}

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

Referenced by get_collation_actual_version().

◆ get_collation_actual_version_libc()

char * get_collation_actual_version_libc ( const char *  collcollate)

Definition at line 911 of file pg_locale_libc.c.

912{
913 char *collversion = NULL;
914
915 if (pg_strcasecmp("C", collcollate) != 0 &&
916 pg_strncasecmp("C.", collcollate, 2) != 0 &&
917 pg_strcasecmp("POSIX", collcollate) != 0)
918 {
919#if defined(__GLIBC__)
920 /* Use the glibc version because we don't have anything better. */
921 collversion = pstrdup(gnu_get_libc_version());
922#elif defined(LC_VERSION_MASK)
923 locale_t loc;
924
925 /* Look up FreeBSD collation version. */
926 loc = newlocale(LC_COLLATE_MASK, collcollate, NULL);
927 if (loc)
928 {
929 collversion =
930 pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
931 freelocale(loc);
932 }
933 else
935 (errmsg("could not load locale \"%s\"", collcollate)));
936#elif defined(WIN32)
937 /*
938 * If we are targeting Windows Vista and above, we can ask for a name
939 * given a collation name (earlier versions required a location code
940 * that we don't have).
941 */
942 NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
943 WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
944
945 MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
946 LOCALE_NAME_MAX_LENGTH);
947 if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
948 {
949 /*
950 * GetNLSVersionEx() wants a language tag such as "en-US", not a
951 * locale name like "English_United States.1252". Until those
952 * values can be prevented from entering the system, or 100%
953 * reliably converted to the more useful tag format, tolerate the
954 * resulting error and report that we have no version data.
955 */
956 if (GetLastError() == ERROR_INVALID_PARAMETER)
957 return NULL;
958
960 (errmsg("could not get collation version for locale \"%s\": error code %lu",
961 collcollate,
962 GetLastError())));
963 }
964 collversion = psprintf("%lu.%lu,%lu.%lu",
965 (version.dwNLSVersion >> 8) & 0xFFFF,
966 version.dwNLSVersion & 0xFF,
967 (version.dwDefinedVersion >> 8) & 0xFFFF,
968 version.dwDefinedVersion & 0xFF);
969#endif
970 }
971
972 return collversion;
973}
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:43

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

Referenced by get_collation_actual_version().

◆ icu_language_tag()

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

Definition at line 1502 of file pg_locale.c.

1503{
1504#ifdef USE_ICU
1505 UErrorCode status;
1506 char *langtag;
1507 size_t buflen = 32; /* arbitrary starting buffer size */
1508 const bool strict = true;
1509
1510 /*
1511 * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
1512 * RFC5646 section 4.4). Additionally, in older ICU versions,
1513 * uloc_toLanguageTag() doesn't always return the ultimate length on the
1514 * first call, necessitating a loop.
1515 */
1516 langtag = palloc(buflen);
1517 while (true)
1518 {
1519 status = U_ZERO_ERROR;
1520 uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
1521
1522 /* try again if the buffer is not large enough */
1523 if ((status == U_BUFFER_OVERFLOW_ERROR ||
1524 status == U_STRING_NOT_TERMINATED_WARNING) &&
1525 buflen < MaxAllocSize)
1526 {
1527 buflen = Min(buflen * 2, MaxAllocSize);
1528 langtag = repalloc(langtag, buflen);
1529 continue;
1530 }
1531
1532 break;
1533 }
1534
1535 if (U_FAILURE(status))
1536 {
1537 pfree(langtag);
1538
1539 if (elevel > 0)
1540 ereport(elevel,
1541 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1542 errmsg("could not convert locale name \"%s\" to language tag: %s",
1543 loc_str, u_errorName(status))));
1544 return NULL;
1545 }
1546
1547 return langtag;
1548#else /* not USE_ICU */
1549 ereport(ERROR,
1550 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1551 errmsg("ICU is not supported in this build")));
1552 return NULL; /* keep compiler quiet */
1553#endif /* not USE_ICU */
1554}
#define Min(x, y)
Definition: c.h:1003
#define MaxAllocSize
Definition: fe_memutils.h:22
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void * palloc(Size size)
Definition: mcxt.c:1365

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

1561{
1562#ifdef USE_ICU
1563 UCollator *collator;
1564 UErrorCode status;
1565 char lang[ULOC_LANG_CAPACITY];
1566 bool found = false;
1567 int elevel = icu_validation_level;
1568
1569 /* no validation */
1570 if (elevel < 0)
1571 return;
1572
1573 /* downgrade to WARNING during pg_upgrade */
1574 if (IsBinaryUpgrade && elevel > WARNING)
1575 elevel = WARNING;
1576
1577 /* validate that we can extract the language */
1578 status = U_ZERO_ERROR;
1579 uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
1580 if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
1581 {
1582 ereport(elevel,
1583 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1584 errmsg("could not get language from ICU locale \"%s\": %s",
1585 loc_str, u_errorName(status)),
1586 errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
1587 "icu_validation_level", "disabled")));
1588 return;
1589 }
1590
1591 /* check for special language name */
1592 if (strcmp(lang, "") == 0 ||
1593 strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
1594 found = true;
1595
1596 /* search for matching language within ICU */
1597 for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
1598 {
1599 const char *otherloc = uloc_getAvailable(i);
1600 char otherlang[ULOC_LANG_CAPACITY];
1601
1602 status = U_ZERO_ERROR;
1603 uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
1604 if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
1605 continue;
1606
1607 if (strcmp(lang, otherlang) == 0)
1608 found = true;
1609 }
1610
1611 if (!found)
1612 ereport(elevel,
1613 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1614 errmsg("ICU locale \"%s\" has unknown language \"%s\"",
1615 loc_str, lang),
1616 errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
1617 "icu_validation_level", "disabled")));
1618
1619 /* check that it can be opened */
1620 collator = pg_ucol_open(loc_str);
1621 ucol_close(collator);
1622#else /* not USE_ICU */
1623 /* could get here if a collation was created by a build with ICU */
1624 ereport(ERROR,
1625 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1626 errmsg("ICU is not supported in this build")));
1627#endif /* not USE_ICU */
1628}
bool IsBinaryUpgrade
Definition: globals.c:121
int icu_validation_level
Definition: pg_locale.c:88

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

1125{
1126 HeapTuple tup;
1127 Form_pg_database dbform;
1128 pg_locale_t result;
1129
1130 Assert(default_locale == NULL);
1131
1132 /* Fetch our pg_database row normally, via syscache */
1133 tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
1134 if (!HeapTupleIsValid(tup))
1135 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1136 dbform = (Form_pg_database) GETSTRUCT(tup);
1137
1138 if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
1139 result = create_pg_locale_builtin(DEFAULT_COLLATION_OID,
1141 else if (dbform->datlocprovider == COLLPROVIDER_ICU)
1142 result = create_pg_locale_icu(DEFAULT_COLLATION_OID,
1144 else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
1145 result = create_pg_locale_libc(DEFAULT_COLLATION_OID,
1147 else
1148 /* shouldn't happen */
1149 PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
1150
1151 result->is_default = true;
1152 ReleaseSysCache(tup);
1153
1154 default_locale = result;
1155}
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
static pg_locale_t default_locale
Definition: pg_locale.c:105

References Assert(), create_pg_locale_builtin(), create_pg_locale_icu(), create_pg_locale_libc(), default_locale, elog, ERROR, GETSTRUCT(), HeapTupleIsValid, pg_locale_struct::is_default, MyDatabaseId, ObjectIdGetDatum(), PGLOCALE_SUPPORT_ERROR, ReleaseSysCache(), SearchSysCache1(), and TopMemoryContext.

Referenced by CheckMyDatabase().

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1166 of file pg_locale.c.

1167{
1168 collation_cache_entry *cache_entry;
1169 bool found;
1170
1171 if (collid == DEFAULT_COLLATION_OID)
1172 return default_locale;
1173
1174 if (!OidIsValid(collid))
1175 elog(ERROR, "cache lookup failed for collation %u", collid);
1176
1178
1181
1182 if (CollationCache == NULL)
1183 {
1185 "collation cache",
1187 CollationCache = collation_cache_create(CollationCacheContext,
1188 16, NULL);
1189 }
1190
1191 cache_entry = collation_cache_insert(CollationCache, collid, &found);
1192 if (!found)
1193 {
1194 /*
1195 * Make sure cache entry is marked invalid, in case we fail before
1196 * setting things.
1197 */
1198 cache_entry->locale = 0;
1199 }
1200
1201 if (cache_entry->locale == 0)
1202 {
1204 }
1205
1207 last_collation_cache_locale = cache_entry->locale;
1208
1209 return cache_entry->locale;
1210}
#define OidIsValid(objectId)
Definition: c.h:774
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static pg_locale_t last_collation_cache_locale
Definition: pg_locale.c:144
static pg_locale_t create_pg_locale(Oid collid, MemoryContext context)
Definition: pg_locale.c:1042
static MemoryContext CollationCacheContext
Definition: pg_locale.c:136
static collation_cache_hash * CollationCache
Definition: pg_locale.c:137
static Oid last_collation_cache_oid
Definition: pg_locale.c:143
static void AssertCouldGetRelation(void)
Definition: relcache.h:44
Definition: pg_locale.c:114
pg_locale_t locale
Definition: pg_locale.c:116

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, AssertCouldGetRelation(), CollationCache, CollationCacheContext, collid, create_pg_locale(), default_locale, elog, ERROR, last_collation_cache_locale, last_collation_cache_oid, collation_cache_entry::locale, OidIsValid, and TopMemoryContext.

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_casefold(), str_initcap(), str_tolower(), str_toupper(), text_position(), 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 165 of file pg_locale.c.

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

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

1271{
1272 return locale->collate->strncoll(arg1, -1, arg2, -1, locale);
1273}

References locale.

Referenced by varstrfastcmp_locale().

◆ pg_strfold()

size_t pg_strfold ( char *  dst,
size_t  dstsize,
const char *  src,
ssize_t  srclen,
pg_locale_t  locale 
)

Definition at line 1255 of file pg_locale.c.

1257{
1258 if (locale->ctype->strfold)
1259 return locale->ctype->strfold(dst, dstsize, src, srclen, locale);
1260 else
1261 return locale->ctype->strlower(dst, dstsize, src, srclen, locale);
1262}

References locale.

Referenced by str_casefold().

◆ pg_strlower()

size_t pg_strlower ( char *  dst,
size_t  dstsize,
const char *  src,
ssize_t  srclen,
pg_locale_t  locale 
)

Definition at line 1234 of file pg_locale.c.

1236{
1237 return locale->ctype->strlower(dst, dstsize, src, srclen, locale);
1238}

References locale.

Referenced by str_tolower().

◆ pg_strncoll()

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

Definition at line 1290 of file pg_locale.c.

1292{
1293 return locale->collate->strncoll(arg1, len1, arg2, len2, locale);
1294}

References locale.

Referenced by MatchText(), text_position_next_internal(), and 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 1345 of file pg_locale.c.

1347{
1348 return locale->collate->strnxfrm(dest, destsize, src, srclen, locale);
1349}

References generate_unaccent_rules::dest, and locale.

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

1394{
1395 return locale->collate->strnxfrm_prefix(dest, destsize, src, srclen, locale);
1396}

References generate_unaccent_rules::dest, and locale.

◆ pg_strtitle()

size_t pg_strtitle ( char *  dst,
size_t  dstsize,
const char *  src,
ssize_t  srclen,
pg_locale_t  locale 
)

Definition at line 1241 of file pg_locale.c.

1243{
1244 return locale->ctype->strtitle(dst, dstsize, src, srclen, locale);
1245}

References locale.

Referenced by str_initcap().

◆ pg_strupper()

size_t pg_strupper ( char *  dst,
size_t  dstsize,
const char *  src,
ssize_t  srclen,
pg_locale_t  locale 
)

Definition at line 1248 of file pg_locale.c.

1250{
1251 return locale->ctype->strupper(dst, dstsize, src, srclen, locale);
1252}

References locale.

Referenced by str_toupper().

◆ pg_strxfrm()

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

Definition at line 1320 of file pg_locale.c.

1321{
1322 return locale->collate->strnxfrm(dest, destsize, src, -1, locale);
1323}

References generate_unaccent_rules::dest, and locale.

Referenced by convert_string_datum(), and varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 1304 of file pg_locale.c.

1305{
1306 /*
1307 * locale->collate->strnxfrm is still a required method, even if it may
1308 * have the wrong behavior, because the planner uses it for estimates in
1309 * some cases.
1310 */
1311 return locale->collate->strxfrm_is_safe;
1312}

References locale.

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

1369{
1370 return locale->collate->strnxfrm_prefix(dest, destsize, src, -1, locale);
1371}

References generate_unaccent_rules::dest, and locale.

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_prefix_enabled()

bool pg_strxfrm_prefix_enabled ( pg_locale_t  locale)

Definition at line 1356 of file pg_locale.c.

1357{
1358 return (locale->collate->strnxfrm_prefix != NULL);
1359}

References locale.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv * PGLC_localeconv ( void  )

Definition at line 499 of file pg_locale.c.

500{
501 static struct lconv CurrentLocaleConv;
502 static bool CurrentLocaleConvAllocated = false;
503 struct lconv *extlconv;
504 struct lconv tmp;
505 struct lconv worklconv = {0};
506
507 /* Did we do it already? */
509 return &CurrentLocaleConv;
510
511 /* Free any already-allocated storage */
512 if (CurrentLocaleConvAllocated)
513 {
514 free_struct_lconv(&CurrentLocaleConv);
515 CurrentLocaleConvAllocated = false;
516 }
517
518 /*
519 * Use thread-safe method of obtaining a copy of lconv from the operating
520 * system.
521 */
524 &tmp) != 0)
525 elog(ERROR,
526 "could not get lconv for LC_MONETARY = \"%s\", LC_NUMERIC = \"%s\": %m",
528
529 /* Must copy data now so we can re-encode it. */
530 extlconv = &tmp;
531 worklconv.decimal_point = strdup(extlconv->decimal_point);
532 worklconv.thousands_sep = strdup(extlconv->thousands_sep);
533 worklconv.grouping = strdup(extlconv->grouping);
534 worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
535 worklconv.currency_symbol = strdup(extlconv->currency_symbol);
536 worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
537 worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
538 worklconv.mon_grouping = strdup(extlconv->mon_grouping);
539 worklconv.positive_sign = strdup(extlconv->positive_sign);
540 worklconv.negative_sign = strdup(extlconv->negative_sign);
541 /* Copy scalar fields as well */
542 worklconv.int_frac_digits = extlconv->int_frac_digits;
543 worklconv.frac_digits = extlconv->frac_digits;
544 worklconv.p_cs_precedes = extlconv->p_cs_precedes;
545 worklconv.p_sep_by_space = extlconv->p_sep_by_space;
546 worklconv.n_cs_precedes = extlconv->n_cs_precedes;
547 worklconv.n_sep_by_space = extlconv->n_sep_by_space;
548 worklconv.p_sign_posn = extlconv->p_sign_posn;
549 worklconv.n_sign_posn = extlconv->n_sign_posn;
550
551 /* Free the contents of the object populated by pg_localeconv_r(). */
552 pg_localeconv_free(&tmp);
553
554 /* If any of the preceding strdup calls failed, complain now. */
555 if (!struct_lconv_is_valid(&worklconv))
557 (errcode(ERRCODE_OUT_OF_MEMORY),
558 errmsg("out of memory")));
559
560 PG_TRY();
561 {
562 int encoding;
563
564 /*
565 * Now we must perform encoding conversion from whatever's associated
566 * with the locales into the database encoding. If we can't identify
567 * the encoding implied by LC_NUMERIC or LC_MONETARY (ie we get -1),
568 * use PG_SQL_ASCII, which will result in just validating that the
569 * strings are OK in the database encoding.
570 */
572 if (encoding < 0)
574
575 db_encoding_convert(encoding, &worklconv.decimal_point);
576 db_encoding_convert(encoding, &worklconv.thousands_sep);
577 /* grouping is not text and does not require conversion */
578
580 if (encoding < 0)
582
583 db_encoding_convert(encoding, &worklconv.int_curr_symbol);
584 db_encoding_convert(encoding, &worklconv.currency_symbol);
585 db_encoding_convert(encoding, &worklconv.mon_decimal_point);
586 db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
587 /* mon_grouping is not text and does not require conversion */
588 db_encoding_convert(encoding, &worklconv.positive_sign);
589 db_encoding_convert(encoding, &worklconv.negative_sign);
590 }
591 PG_CATCH();
592 {
593 free_struct_lconv(&worklconv);
594 PG_RE_THROW();
595 }
596 PG_END_TRY();
597
598 /*
599 * Everything is good, so save the results.
600 */
601 CurrentLocaleConv = worklconv;
602 CurrentLocaleConvAllocated = true;
604 return &CurrentLocaleConv;
605}
#define PG_RE_THROW()
Definition: elog.h:405
#define PG_TRY(...)
Definition: elog.h:372
#define PG_END_TRY(...)
Definition: elog.h:397
#define PG_CATCH(...)
Definition: elog.h:382
char * locale_numeric
Definition: pg_locale.c:85
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:469
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:419
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:438
char * locale_monetary
Definition: pg_locale.c:84
int pg_localeconv_r(const char *lc_monetary, const char *lc_numeric, struct lconv *output)
void pg_localeconv_free(struct lconv *lconv)

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

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

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 438 of file pg_locale.c.

439{
440 if (s->decimal_point == NULL)
441 return false;
442 if (s->thousands_sep == NULL)
443 return false;
444 if (s->grouping == NULL)
445 return false;
446 if (s->int_curr_symbol == NULL)
447 return false;
448 if (s->currency_symbol == NULL)
449 return false;
450 if (s->mon_decimal_point == NULL)
451 return false;
452 if (s->mon_thousands_sep == NULL)
453 return false;
454 if (s->mon_grouping == NULL)
455 return false;
456 if (s->positive_sign == NULL)
457 return false;
458 if (s->negative_sign == NULL)
459 return false;
460 return true;
461}

Referenced by PGLC_localeconv().

Variable Documentation

◆ CollationCache

collation_cache_hash* CollationCache = NULL
static

Definition at line 137 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ CollationCacheContext

MemoryContext CollationCacheContext = NULL
static

Definition at line 136 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 109 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 108 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

Definition at line 103 of file pg_locale.c.

Referenced by CheckMyDatabase(), t_isalnum(), t_isalpha(), and TParserInit().

◆ default_locale

pg_locale_t default_locale = NULL
static

Definition at line 105 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 88 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 144 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 143 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ locale_messages

char* locale_messages

Definition at line 83 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 84 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 85 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 86 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 97 of file pg_locale.c.

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

◆ localized_abbrev_months

char* localized_abbrev_months[12+1]

Definition at line 99 of file pg_locale.c.

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

◆ localized_full_days

char* localized_full_days[7+1]

Definition at line 98 of file pg_locale.c.

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

◆ localized_full_months

char* localized_full_months[12+1]

Definition at line 100 of file pg_locale.c.

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