PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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

pg_locale_t create_pg_locale_builtin (Oid collid, MemoryContext context)
 
pg_locale_t create_pg_locale_icu (Oid collid, MemoryContext context)
 
pg_locale_t create_pg_locale_libc (Oid collid, MemoryContext context)
 
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)
 
size_t strlower_builtin (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strtitle_builtin (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strupper_builtin (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strlower_icu (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strtitle_icu (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strupper_icu (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strlower_libc (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strtitle_libc (char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
 
size_t strupper_libc (char *dst, size_t dstsize, 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 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)
 
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 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 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 190 of file pg_locale.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 191 of file pg_locale.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   collation_cache_entry

Definition at line 182 of file pg_locale.c.

◆ SH_EQUAL

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

Definition at line 186 of file pg_locale.c.

◆ SH_GET_HASH

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

Definition at line 187 of file pg_locale.c.

◆ SH_HASH_KEY

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

Definition at line 185 of file pg_locale.c.

◆ SH_KEY

#define SH_KEY   collid

Definition at line 184 of file pg_locale.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   Oid

Definition at line 183 of file pg_locale.c.

◆ SH_PREFIX

#define SH_PREFIX   collation_cache

Definition at line 181 of file pg_locale.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 188 of file pg_locale.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

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

461{
462 /*
463 * LC_MESSAGES category does not exist everywhere, but accept it anyway.
464 * We ignore failure, as per comment above.
465 */
466#ifdef LC_MESSAGES
467 (void) pg_perm_setlocale(LC_MESSAGES, newval);
468#endif
469}
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:223

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 397 of file pg_locale.c.

398{
400}
static bool CurrentLocaleConvValid
Definition: pg_locale.c:166

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 409 of file pg_locale.c.

410{
412}

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 421 of file pg_locale.c.

422{
423 CurrentLCTimeValid = false;
424}
static bool CurrentLCTimeValid
Definition: pg_locale.c:167

References CurrentLCTimeValid.

◆ builtin_locale_encoding()

int builtin_locale_encoding ( const char *  locale)

Definition at line 1767 of file pg_locale.c.

1768{
1769 if (strcmp(locale, "C") == 0)
1770 return -1;
1771 if (strcmp(locale, "C.UTF-8") == 0)
1772 return PG_UTF8;
1773
1774 ereport(ERROR,
1775 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1776 errmsg("invalid locale name \"%s\" for builtin provider",
1777 locale)));
1778
1779 return 0; /* keep compiler quiet */
1780}
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 1788 of file pg_locale.c.

1789{
1790 const char *canonical_name = NULL;
1791 int required_encoding;
1792
1793 if (strcmp(locale, "C") == 0)
1794 canonical_name = "C";
1795 else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0)
1796 canonical_name = "C.UTF-8";
1797
1798 if (!canonical_name)
1799 ereport(ERROR,
1800 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1801 errmsg("invalid locale name \"%s\" for builtin provider",
1802 locale)));
1803
1804 required_encoding = builtin_locale_encoding(canonical_name);
1805 if (required_encoding >= 0 && encoding != required_encoding)
1806 ereport(ERROR,
1807 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1808 errmsg("encoding \"%s\" does not match locale \"%s\"",
1810
1811 return canonical_name;
1812}
int32 encoding
Definition: pg_database.h:41
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:1767
#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 839 of file pg_locale.c.

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

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

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

327{
328 char *save;
329 char *res;
330
331 /* Don't let Windows' non-ASCII locale names in. */
332 if (!pg_is_ascii(locale))
333 {
335 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
336 errmsg("locale name \"%s\" contains non-ASCII characters",
337 locale)));
338 return false;
339 }
340
341 if (canonname)
342 *canonname = NULL; /* in case of failure */
343
344 save = setlocale(category, NULL);
345 if (!save)
346 return false; /* won't happen, we hope */
347
348 /* save may be pointing at a modifiable scratch variable, see above. */
349 save = pstrdup(save);
350
351 /* set the locale with setlocale, to see if it accepts it. */
352 res = setlocale(category, locale);
353
354 /* save canonical name if requested. */
355 if (res && canonname)
356 *canonname = pstrdup(res);
357
358 /* restore old value. */
359 if (!setlocale(category, save))
360 elog(WARNING, "failed to restore old locale \"%s\"", save);
361 pfree(save);
362
363 /* Don't let Windows' non-ASCII locale names out. */
364 if (canonname && *canonname && !pg_is_ascii(*canonname))
365 {
367 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
368 errmsg("locale name \"%s\" contains non-ASCII characters",
369 *canonname)));
370 pfree(*canonname);
371 *canonname = NULL;
372 return false;
373 }
374
375 return (res != NULL);
376}
#define WARNING
Definition: elog.h:36
bool pg_is_ascii(const char *str)
Definition: string.c:132

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

438{
439 if (**newval == '\0')
440 {
441 if (source == PGC_S_DEFAULT)
442 return true;
443 else
444 return false;
445 }
446
447 /*
448 * LC_MESSAGES category does not exist everywhere, but accept it anyway
449 *
450 * On Windows, we can't even check the value, so accept blindly
451 */
452#if defined(LC_MESSAGES) && !defined(WIN32)
453 return check_locale(LC_MESSAGES, *newval, NULL);
454#else
455 return true;
456#endif
457}
@ PGC_S_DEFAULT
Definition: guc.h:109
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:326
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 391 of file pg_locale.c.

392{
393 return check_locale(LC_MONETARY, *newval, NULL);
394}

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 403 of file pg_locale.c.

404{
405 return check_locale(LC_NUMERIC, *newval, NULL);
406}

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 415 of file pg_locale.c.

416{
417 return check_locale(LC_TIME, *newval, NULL);
418}

References check_locale(), and newval.

◆ create_pg_locale()

static pg_locale_t create_pg_locale ( Oid  collid,
MemoryContext  context 
)
static

Definition at line 1223 of file pg_locale.c.

1224{
1225 HeapTuple tp;
1226 Form_pg_collation collform;
1227 pg_locale_t result;
1228 Datum datum;
1229 bool isnull;
1230
1231 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1232 if (!HeapTupleIsValid(tp))
1233 elog(ERROR, "cache lookup failed for collation %u", collid);
1234 collform = (Form_pg_collation) GETSTRUCT(tp);
1235
1236 if (collform->collprovider == COLLPROVIDER_BUILTIN)
1238 else if (collform->collprovider == COLLPROVIDER_ICU)
1240 else if (collform->collprovider == COLLPROVIDER_LIBC)
1242 else
1243 /* shouldn't happen */
1244 PGLOCALE_SUPPORT_ERROR(collform->collprovider);
1245
1246 result->is_default = false;
1247
1248 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1249 &isnull);
1250 if (!isnull)
1251 {
1252 char *actual_versionstr;
1253 char *collversionstr;
1254
1255 collversionstr = TextDatumGetCString(datum);
1256
1257 if (collform->collprovider == COLLPROVIDER_LIBC)
1258 datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1259 else
1260 datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1261
1262 actual_versionstr = get_collation_actual_version(collform->collprovider,
1263 TextDatumGetCString(datum));
1264 if (!actual_versionstr)
1265 {
1266 /*
1267 * This could happen when specifying a version in CREATE COLLATION
1268 * but the provider does not support versioning, or manually
1269 * creating a mess in the catalogs.
1270 */
1271 ereport(ERROR,
1272 (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1273 NameStr(collform->collname))));
1274 }
1275
1276 if (strcmp(actual_versionstr, collversionstr) != 0)
1278 (errmsg("collation \"%s\" has version mismatch",
1279 NameStr(collform->collname)),
1280 errdetail("The collation in the database was created using version %s, "
1281 "but the operating system provides version %s.",
1282 collversionstr, actual_versionstr),
1283 errhint("Rebuild all objects affected by this collation and run "
1284 "ALTER COLLATION %s REFRESH VERSION, "
1285 "or build PostgreSQL with the right library version.",
1286 quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1287 NameStr(collform->collname)))));
1288 }
1289
1290 ReleaseSysCache(tp);
1291
1292 return result;
1293}
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:700
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
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:1390
pg_locale_t create_pg_locale_builtin(Oid collid, MemoryContext context)
#define PGLOCALE_SUPPORT_ERROR(provider)
Definition: pg_locale.c:81
pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context)
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
tree context
Definition: radixtree.h:1837
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12954
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:600
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631

References collid, context, create_pg_locale_builtin(), create_pg_locale_icu(), create_pg_locale_libc(), 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 107 of file pg_locale_builtin.c.

108{
109 const char *locstr;
110 pg_locale_t result;
111
112 if (collid == DEFAULT_COLLATION_OID)
113 {
114 HeapTuple tp;
115 Datum datum;
116
118 if (!HeapTupleIsValid(tp))
119 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
120 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
121 Anum_pg_database_datlocale);
122 locstr = TextDatumGetCString(datum);
123 ReleaseSysCache(tp);
124 }
125 else
126 {
127 HeapTuple tp;
128 Datum datum;
129
131 if (!HeapTupleIsValid(tp))
132 elog(ERROR, "cache lookup failed for collation %u", collid);
133 datum = SysCacheGetAttrNotNull(COLLOID, tp,
134 Anum_pg_collation_colllocale);
135 locstr = TextDatumGetCString(datum);
136 ReleaseSysCache(tp);
137 }
138
140
141 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
142
143 result->info.builtin.locale = MemoryContextStrdup(context, locstr);
144 result->provider = COLLPROVIDER_BUILTIN;
145 result->deterministic = true;
146 result->collate_is_c = true;
147 result->ctype_is_c = (strcmp(locstr, "C") == 0);
148
149 return result;
150}
Oid MyDatabaseId
Definition: globals.c:93
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:1788
union pg_locale_struct::@157 info
const char * locale
Definition: pg_locale.h:77
bool deterministic
Definition: pg_locale.h:69
struct pg_locale_struct::@157::@158 builtin

References pg_locale_struct::builtin, builtin_validate_locale(), pg_locale_struct::collate_is_c, collid, context, pg_locale_struct::ctype_is_c, pg_locale_struct::deterministic, elog, ERROR, GetDatabaseEncoding(), HeapTupleIsValid, pg_locale_struct::info, pg_locale_struct::locale, MemoryContextAllocZero(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), pg_locale_struct::provider, 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 113 of file pg_locale_icu.c.

114{
115#ifdef USE_ICU
116 bool deterministic;
117 const char *iculocstr;
118 const char *icurules = NULL;
119 UCollator *collator;
120 pg_locale_t result;
121
122 if (collid == DEFAULT_COLLATION_OID)
123 {
124 HeapTuple tp;
125 Datum datum;
126 bool isnull;
127
129 if (!HeapTupleIsValid(tp))
130 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
131
132 /* default database collation is always deterministic */
133 deterministic = true;
134 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
135 Anum_pg_database_datlocale);
136 iculocstr = TextDatumGetCString(datum);
137 datum = SysCacheGetAttr(DATABASEOID, tp,
138 Anum_pg_database_daticurules, &isnull);
139 if (!isnull)
140 icurules = TextDatumGetCString(datum);
141
142 ReleaseSysCache(tp);
143 }
144 else
145 {
146 Form_pg_collation collform;
147 HeapTuple tp;
148 Datum datum;
149 bool isnull;
150
152 if (!HeapTupleIsValid(tp))
153 elog(ERROR, "cache lookup failed for collation %u", collid);
154 collform = (Form_pg_collation) GETSTRUCT(tp);
155 deterministic = collform->collisdeterministic;
156 datum = SysCacheGetAttrNotNull(COLLOID, tp,
157 Anum_pg_collation_colllocale);
158 iculocstr = TextDatumGetCString(datum);
159 datum = SysCacheGetAttr(COLLOID, tp,
160 Anum_pg_collation_collicurules, &isnull);
161 if (!isnull)
162 icurules = TextDatumGetCString(datum);
163
164 ReleaseSysCache(tp);
165 }
166
167 collator = make_icu_collator(iculocstr, icurules);
168
169 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
170 result->info.icu.locale = MemoryContextStrdup(context, iculocstr);
171 result->info.icu.ucol = collator;
172 result->provider = COLLPROVIDER_ICU;
173 result->deterministic = deterministic;
174 result->collate_is_c = false;
175 result->ctype_is_c = false;
176
177 return result;
178#else
179 /* could get here if a collation was created by a build with ICU */
181 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
182 errmsg("ICU is not supported in this build")));
183
184 return NULL;
185#endif
186}

References pg_locale_struct::collate_is_c, collid, context, pg_locale_struct::ctype_is_c, pg_locale_struct::deterministic, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, pg_locale_struct::locale, MemoryContextAllocZero(), MemoryContextStrdup(), MyDatabaseId, ObjectIdGetDatum(), pg_locale_struct::provider, 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 379 of file pg_locale_libc.c.

380{
381 const char *collate;
382 const char *ctype;
383 locale_t loc;
384 pg_locale_t result;
385
386 if (collid == DEFAULT_COLLATION_OID)
387 {
388 HeapTuple tp;
389 Datum datum;
390
392 if (!HeapTupleIsValid(tp))
393 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
394 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
395 Anum_pg_database_datcollate);
396 collate = TextDatumGetCString(datum);
397 datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
398 Anum_pg_database_datctype);
399 ctype = TextDatumGetCString(datum);
400
401 ReleaseSysCache(tp);
402 }
403 else
404 {
405 HeapTuple tp;
406 Datum datum;
407
409 if (!HeapTupleIsValid(tp))
410 elog(ERROR, "cache lookup failed for collation %u", collid);
411
412 datum = SysCacheGetAttrNotNull(COLLOID, tp,
413 Anum_pg_collation_collcollate);
414 collate = TextDatumGetCString(datum);
415 datum = SysCacheGetAttrNotNull(COLLOID, tp,
416 Anum_pg_collation_collctype);
417 ctype = TextDatumGetCString(datum);
418
419 ReleaseSysCache(tp);
420 }
421
422
423 loc = make_libc_collator(collate, ctype);
424
425 result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
426 result->provider = COLLPROVIDER_LIBC;
427 result->deterministic = true;
428 result->collate_is_c = (strcmp(collate, "C") == 0) ||
429 (strcmp(collate, "POSIX") == 0);
430 result->ctype_is_c = (strcmp(ctype, "C") == 0) ||
431 (strcmp(ctype, "POSIX") == 0);
432 result->info.lt = loc;
433
434 return result;
435}
static locale_t make_libc_collator(const char *collate, const char *ctype)
locale_t lt
Definition: pg_locale.h:79
#define locale_t
Definition: win32_port.h:442

References pg_locale_struct::collate_is_c, collid, context, pg_locale_struct::ctype_is_c, pg_locale_struct::deterministic, elog, ERROR, HeapTupleIsValid, pg_locale_struct::info, locale_t, pg_locale_struct::lt, make_libc_collator(), MemoryContextAllocZero(), MyDatabaseId, ObjectIdGetDatum(), pg_locale_struct::provider, 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 527 of file pg_locale.c.

528{
529 char *pstr;
530 char *mstr;
531
532 /* convert the string to the database encoding */
533 pstr = pg_any_to_server(*str, strlen(*str), encoding);
534 if (pstr == *str)
535 return; /* no conversion happened */
536
537 /* need it malloc'd not palloc'd */
538 mstr = strdup(pstr);
539 if (mstr == NULL)
541 (errcode(ERRCODE_OUT_OF_MEMORY),
542 errmsg("out of memory")));
543
544 /* replace old string */
545 free(*str);
546 *str = mstr;
547
548 pfree(pstr);
549}
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 477 of file pg_locale.c.

478{
479 free(s->decimal_point);
480 free(s->thousands_sep);
481 free(s->grouping);
482 free(s->int_curr_symbol);
483 free(s->currency_symbol);
484 free(s->mon_decimal_point);
485 free(s->mon_thousands_sep);
486 free(s->mon_grouping);
487 free(s->positive_sign);
488 free(s->negative_sign);
489}

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1390 of file pg_locale.c.

1391{
1392 char *collversion = NULL;
1393
1394 /*
1395 * The only two supported locales (C and C.UTF-8) are both based on memcmp
1396 * and are not expected to change, but track the version anyway.
1397 *
1398 * Note that the character semantics may change for some locales, but the
1399 * collation version only tracks changes to sort order.
1400 */
1401 if (collprovider == COLLPROVIDER_BUILTIN)
1402 {
1403 if (strcmp(collcollate, "C") == 0)
1404 return "1";
1405 else if (strcmp(collcollate, "C.UTF-8") == 0)
1406 return "1";
1407 else
1408 ereport(ERROR,
1409 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1410 errmsg("invalid locale name \"%s\" for builtin provider",
1411 collcollate)));
1412 }
1413
1414#ifdef USE_ICU
1415 if (collprovider == COLLPROVIDER_ICU)
1416 {
1417 UCollator *collator;
1418 UVersionInfo versioninfo;
1419 char buf[U_MAX_VERSION_STRING_LENGTH];
1420
1421 collator = pg_ucol_open(collcollate);
1422
1423 ucol_getVersion(collator, versioninfo);
1424 ucol_close(collator);
1425
1426 u_versionToString(versioninfo, buf);
1427 collversion = pstrdup(buf);
1428 }
1429 else
1430#endif
1431 if (collprovider == COLLPROVIDER_LIBC &&
1432 pg_strcasecmp("C", collcollate) != 0 &&
1433 pg_strncasecmp("C.", collcollate, 2) != 0 &&
1434 pg_strcasecmp("POSIX", collcollate) != 0)
1435 {
1436#if defined(__GLIBC__)
1437 /* Use the glibc version because we don't have anything better. */
1438 collversion = pstrdup(gnu_get_libc_version());
1439#elif defined(LC_VERSION_MASK)
1440 locale_t loc;
1441
1442 /* Look up FreeBSD collation version. */
1443 loc = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1444 if (loc)
1445 {
1446 collversion =
1447 pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1448 freelocale(loc);
1449 }
1450 else
1451 ereport(ERROR,
1452 (errmsg("could not load locale \"%s\"", collcollate)));
1453#elif defined(WIN32)
1454 /*
1455 * If we are targeting Windows Vista and above, we can ask for a name
1456 * given a collation name (earlier versions required a location code
1457 * that we don't have).
1458 */
1459 NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1460 WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1461
1462 MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1463 LOCALE_NAME_MAX_LENGTH);
1464 if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1465 {
1466 /*
1467 * GetNLSVersionEx() wants a language tag such as "en-US", not a
1468 * locale name like "English_United States.1252". Until those
1469 * values can be prevented from entering the system, or 100%
1470 * reliably converted to the more useful tag format, tolerate the
1471 * resulting error and report that we have no version data.
1472 */
1473 if (GetLastError() == ERROR_INVALID_PARAMETER)
1474 return NULL;
1475
1476 ereport(ERROR,
1477 (errmsg("could not get collation version for locale \"%s\": error code %lu",
1478 collcollate,
1479 GetLastError())));
1480 }
1481 collversion = psprintf("%lu.%lu,%lu.%lu",
1482 (version.dwNLSVersion >> 8) & 0xFFFF,
1483 version.dwNLSVersion & 0xFF,
1484 (version.dwDefinedVersion >> 8) & 0xFFFF,
1485 version.dwDefinedVersion & 0xFF);
1486#endif
1487 }
1488
1489 return collversion;
1490}
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 buf, ereport, errcode(), errmsg(), ERROR, locale_t, pg_strcasecmp(), pg_strncasecmp(), psprintf(), and pstrdup().

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

◆ icu_language_tag()

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

Definition at line 1826 of file pg_locale.c.

1827{
1828#ifdef USE_ICU
1829 UErrorCode status;
1830 char *langtag;
1831 size_t buflen = 32; /* arbitrary starting buffer size */
1832 const bool strict = true;
1833
1834 /*
1835 * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
1836 * RFC5646 section 4.4). Additionally, in older ICU versions,
1837 * uloc_toLanguageTag() doesn't always return the ultimate length on the
1838 * first call, necessitating a loop.
1839 */
1840 langtag = palloc(buflen);
1841 while (true)
1842 {
1843 status = U_ZERO_ERROR;
1844 uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
1845
1846 /* try again if the buffer is not large enough */
1847 if ((status == U_BUFFER_OVERFLOW_ERROR ||
1848 status == U_STRING_NOT_TERMINATED_WARNING) &&
1849 buflen < MaxAllocSize)
1850 {
1851 buflen = Min(buflen * 2, MaxAllocSize);
1852 langtag = repalloc(langtag, buflen);
1853 continue;
1854 }
1855
1856 break;
1857 }
1858
1859 if (U_FAILURE(status))
1860 {
1861 pfree(langtag);
1862
1863 if (elevel > 0)
1864 ereport(elevel,
1865 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1866 errmsg("could not convert locale name \"%s\" to language tag: %s",
1867 loc_str, u_errorName(status))));
1868 return NULL;
1869 }
1870
1871 return langtag;
1872#else /* not USE_ICU */
1873 ereport(ERROR,
1874 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1875 errmsg("ICU is not supported in this build")));
1876 return NULL; /* keep compiler quiet */
1877#endif /* not USE_ICU */
1878}
#define Min(x, y)
Definition: c.h:958
#define MaxAllocSize
Definition: fe_memutils.h:22
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * palloc(Size size)
Definition: mcxt.c:1317

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

1885{
1886#ifdef USE_ICU
1887 UCollator *collator;
1888 UErrorCode status;
1889 char lang[ULOC_LANG_CAPACITY];
1890 bool found = false;
1891 int elevel = icu_validation_level;
1892
1893 /* no validation */
1894 if (elevel < 0)
1895 return;
1896
1897 /* downgrade to WARNING during pg_upgrade */
1898 if (IsBinaryUpgrade && elevel > WARNING)
1899 elevel = WARNING;
1900
1901 /* validate that we can extract the language */
1902 status = U_ZERO_ERROR;
1903 uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
1904 if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
1905 {
1906 ereport(elevel,
1907 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1908 errmsg("could not get language from ICU locale \"%s\": %s",
1909 loc_str, u_errorName(status)),
1910 errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
1911 "icu_validation_level", "disabled")));
1912 return;
1913 }
1914
1915 /* check for special language name */
1916 if (strcmp(lang, "") == 0 ||
1917 strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
1918 found = true;
1919
1920 /* search for matching language within ICU */
1921 for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
1922 {
1923 const char *otherloc = uloc_getAvailable(i);
1924 char otherlang[ULOC_LANG_CAPACITY];
1925
1926 status = U_ZERO_ERROR;
1927 uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
1928 if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
1929 continue;
1930
1931 if (strcmp(lang, otherlang) == 0)
1932 found = true;
1933 }
1934
1935 if (!found)
1936 ereport(elevel,
1937 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1938 errmsg("ICU locale \"%s\" has unknown language \"%s\"",
1939 loc_str, lang),
1940 errhint("To disable ICU locale validation, set the parameter \"%s\" to \"%s\".",
1941 "icu_validation_level", "disabled")));
1942
1943 /* check that it can be opened */
1944 collator = pg_ucol_open(loc_str);
1945 ucol_close(collator);
1946#else /* not USE_ICU */
1947 /* could get here if a collation was created by a build with ICU */
1948 ereport(ERROR,
1949 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1950 errmsg("ICU is not supported in this build")));
1951#endif /* not USE_ICU */
1952}
bool IsBinaryUpgrade
Definition: globals.c:120
int icu_validation_level
Definition: pg_locale.c:146

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

1300{
1301 HeapTuple tup;
1302 Form_pg_database dbform;
1303 pg_locale_t result;
1304
1305 Assert(default_locale == NULL);
1306
1307 /* Fetch our pg_database row normally, via syscache */
1308 tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
1309 if (!HeapTupleIsValid(tup))
1310 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1311 dbform = (Form_pg_database) GETSTRUCT(tup);
1312
1313 if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
1314 result = create_pg_locale_builtin(DEFAULT_COLLATION_OID,
1316 else if (dbform->datlocprovider == COLLPROVIDER_ICU)
1317 result = create_pg_locale_icu(DEFAULT_COLLATION_OID,
1319 else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
1320 result = create_pg_locale_libc(DEFAULT_COLLATION_OID,
1322 else
1323 /* shouldn't happen */
1324 PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
1325
1326 result->is_default = true;
1327 ReleaseSysCache(tup);
1328
1329 default_locale = result;
1330}
#define Assert(condition)
Definition: c.h:812
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
static pg_locale_t default_locale
Definition: pg_locale.c:163

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

1342{
1343 collation_cache_entry *cache_entry;
1344 bool found;
1345
1346 if (collid == DEFAULT_COLLATION_OID)
1347 return default_locale;
1348
1349 if (!OidIsValid(collid))
1350 elog(ERROR, "cache lookup failed for collation %u", collid);
1351
1354
1355 if (CollationCache == NULL)
1356 {
1358 "collation cache",
1360 CollationCache = collation_cache_create(CollationCacheContext,
1361 16, NULL);
1362 }
1363
1364 cache_entry = collation_cache_insert(CollationCache, collid, &found);
1365 if (!found)
1366 {
1367 /*
1368 * Make sure cache entry is marked invalid, in case we fail before
1369 * setting things.
1370 */
1371 cache_entry->locale = 0;
1372 }
1373
1374 if (cache_entry->locale == 0)
1375 {
1377 }
1378
1380 last_collation_cache_locale = cache_entry->locale;
1381
1382 return cache_entry->locale;
1383}
#define OidIsValid(objectId)
Definition: c.h:729
#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:202
static pg_locale_t create_pg_locale(Oid collid, MemoryContext context)
Definition: pg_locale.c:1223
static MemoryContext CollationCacheContext
Definition: pg_locale.c:194
static collation_cache_hash * CollationCache
Definition: pg_locale.c:195
static Oid last_collation_cache_oid
Definition: pg_locale.c:201
Definition: pg_locale.c:172
pg_locale_t locale
Definition: pg_locale.c:174

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, 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_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 223 of file pg_locale.c.

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

1556{
1557 int result;
1558
1559 if (locale->provider == COLLPROVIDER_LIBC)
1560 result = strncoll_libc(arg1, -1, arg2, -1, locale);
1561#ifdef USE_ICU
1562 else if (locale->provider == COLLPROVIDER_ICU)
1563 result = strncoll_icu(arg1, -1, arg2, -1, locale);
1564#endif
1565 else
1566 /* shouldn't happen */
1567 PGLOCALE_SUPPORT_ERROR(locale->provider);
1568
1569 return result;
1570}
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_strlower()

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

Definition at line 1493 of file pg_locale.c.

1495{
1496 if (locale->provider == COLLPROVIDER_BUILTIN)
1497 return strlower_builtin(dst, dstsize, src, srclen, locale);
1498#ifdef USE_ICU
1499 else if (locale->provider == COLLPROVIDER_ICU)
1500 return strlower_icu(dst, dstsize, src, srclen, locale);
1501#endif
1502 else if (locale->provider == COLLPROVIDER_LIBC)
1503 return strlower_libc(dst, dstsize, src, srclen, locale);
1504 else
1505 /* shouldn't happen */
1506 PGLOCALE_SUPPORT_ERROR(locale->provider);
1507
1508 return 0; /* keep compiler quiet */
1509}
size_t strlower_icu(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strlower_builtin(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strlower_libc(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, PGLOCALE_SUPPORT_ERROR, strlower_builtin(), strlower_icu(), and strlower_libc().

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

1589{
1590 int result;
1591
1592 if (locale->provider == COLLPROVIDER_LIBC)
1593 result = strncoll_libc(arg1, len1, arg2, len2, locale);
1594#ifdef USE_ICU
1595 else if (locale->provider == COLLPROVIDER_ICU)
1596 result = strncoll_icu(arg1, len1, arg2, len2, locale);
1597#endif
1598 else
1599 /* shouldn't happen */
1600 PGLOCALE_SUPPORT_ERROR(locale->provider);
1601
1602 return result;
1603}

References locale, PGLOCALE_SUPPORT_ERROR, and strncoll_libc().

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

1682{
1683 size_t result = 0; /* keep compiler quiet */
1684
1685 if (locale->provider == COLLPROVIDER_LIBC)
1686 result = strnxfrm_libc(dest, destsize, src, srclen, locale);
1687#ifdef USE_ICU
1688 else if (locale->provider == COLLPROVIDER_ICU)
1689 result = strnxfrm_icu(dest, destsize, src, srclen, locale);
1690#endif
1691 else
1692 /* shouldn't happen */
1693 PGLOCALE_SUPPORT_ERROR(locale->provider);
1694
1695 return result;
1696}
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 1747 of file pg_locale.c.

1749{
1750 size_t result = 0; /* keep compiler quiet */
1751
1752#ifdef USE_ICU
1753 if (locale->provider == COLLPROVIDER_ICU)
1754 result = strnxfrm_prefix_icu(dest, destsize, src, -1, locale);
1755 else
1756#endif
1757 PGLOCALE_SUPPORT_ERROR(locale->provider);
1758
1759 return result;
1760}

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by pg_strxfrm_prefix().

◆ pg_strtitle()

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

Definition at line 1512 of file pg_locale.c.

1514{
1515 if (locale->provider == COLLPROVIDER_BUILTIN)
1516 return strtitle_builtin(dst, dstsize, src, srclen, locale);
1517#ifdef USE_ICU
1518 else if (locale->provider == COLLPROVIDER_ICU)
1519 return strtitle_icu(dst, dstsize, src, srclen, locale);
1520#endif
1521 else if (locale->provider == COLLPROVIDER_LIBC)
1522 return strtitle_libc(dst, dstsize, src, srclen, locale);
1523 else
1524 /* shouldn't happen */
1525 PGLOCALE_SUPPORT_ERROR(locale->provider);
1526
1527 return 0; /* keep compiler quiet */
1528}
size_t strtitle_libc(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strtitle_icu(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strtitle_builtin(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, PGLOCALE_SUPPORT_ERROR, strtitle_builtin(), strtitle_icu(), and strtitle_libc().

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

1533{
1534 if (locale->provider == COLLPROVIDER_BUILTIN)
1535 return strupper_builtin(dst, dstsize, src, srclen, locale);
1536#ifdef USE_ICU
1537 else if (locale->provider == COLLPROVIDER_ICU)
1538 return strupper_icu(dst, dstsize, src, srclen, locale);
1539#endif
1540 else if (locale->provider == COLLPROVIDER_LIBC)
1541 return strupper_libc(dst, dstsize, src, srclen, locale);
1542 else
1543 /* shouldn't happen */
1544 PGLOCALE_SUPPORT_ERROR(locale->provider);
1545
1546 return 0; /* keep compiler quiet */
1547}
size_t strupper_icu(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strupper_libc(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
size_t strupper_builtin(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, PGLOCALE_SUPPORT_ERROR, strupper_builtin(), strupper_icu(), and strupper_libc().

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

1644{
1645 size_t result = 0; /* keep compiler quiet */
1646
1647 if (locale->provider == COLLPROVIDER_LIBC)
1648 result = strnxfrm_libc(dest, destsize, src, -1, locale);
1649#ifdef USE_ICU
1650 else if (locale->provider == COLLPROVIDER_ICU)
1651 result = strnxfrm_icu(dest, destsize, src, -1, locale);
1652#endif
1653 else
1654 /* shouldn't happen */
1655 PGLOCALE_SUPPORT_ERROR(locale->provider);
1656
1657 return result;
1658}

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

1621{
1622 if (locale->provider == COLLPROVIDER_LIBC)
1623#ifdef TRUST_STRXFRM
1624 return true;
1625#else
1626 return false;
1627#endif
1628 else if (locale->provider == COLLPROVIDER_ICU)
1629 return true;
1630 else
1631 /* shouldn't happen */
1632 PGLOCALE_SUPPORT_ERROR(locale->provider);
1633
1634 return false; /* keep compiler quiet */
1635}

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

1724{
1725 return pg_strnxfrm_prefix(dest, destsize, src, -1, locale);
1726}
size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
Definition: pg_locale.c:1747

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

1704{
1705 if (locale->provider == COLLPROVIDER_LIBC)
1706 return false;
1707 else if (locale->provider == COLLPROVIDER_ICU)
1708 return true;
1709 else
1710 /* shouldn't happen */
1711 PGLOCALE_SUPPORT_ERROR(locale->provider);
1712
1713 return false; /* keep compiler quiet */
1714}

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv * PGLC_localeconv ( void  )

Definition at line 557 of file pg_locale.c.

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

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

◆ strlower_builtin()

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

Definition at line 77 of file pg_locale_builtin.c.

79{
80 return unicode_strlower(dest, destsize, src, srclen);
81}
size_t unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen)
Definition: unicode_case.c:68

References generate_unaccent_rules::dest, and unicode_strlower().

Referenced by pg_strlower().

◆ strlower_icu()

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

Referenced by pg_strlower().

◆ strlower_libc()

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

Definition at line 81 of file pg_locale_libc.c.

83{
85 return strlower_libc_mb(dst, dstsize, src, srclen, locale);
86 else
87 return strlower_libc_sb(dst, dstsize, src, srclen, locale);
88}
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1546
static size_t strlower_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static size_t strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, pg_database_encoding_max_length(), strlower_libc_mb(), and strlower_libc_sb().

Referenced by pg_strlower().

◆ strncoll_libc()

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

Definition at line 517 of file pg_locale_libc.c.

519{
520 char sbuf[TEXTBUFLEN];
521 char *buf = sbuf;
522 size_t bufsize1 = (len1 == -1) ? 0 : len1 + 1;
523 size_t bufsize2 = (len2 == -1) ? 0 : len2 + 1;
524 const char *arg1n;
525 const char *arg2n;
526 int result;
527
528 Assert(locale->provider == COLLPROVIDER_LIBC);
529
530#ifdef WIN32
531 /* check for this case before doing the work for nul-termination */
533 return strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
534#endif /* WIN32 */
535
536 if (bufsize1 + bufsize2 > TEXTBUFLEN)
537 buf = palloc(bufsize1 + bufsize2);
538
539 /* nul-terminate arguments if necessary */
540 if (len1 == -1)
541 {
542 arg1n = arg1;
543 }
544 else
545 {
546 char *buf1 = buf;
547
548 memcpy(buf1, arg1, len1);
549 buf1[len1] = '\0';
550 arg1n = buf1;
551 }
552
553 if (len2 == -1)
554 {
555 arg2n = arg2;
556 }
557 else
558 {
559 char *buf2 = buf + bufsize1;
560
561 memcpy(buf2, arg2, len2);
562 buf2[len2] = '\0';
563 arg2n = buf2;
564 }
565
566 result = strcoll_l(arg1n, arg2n, locale->info.lt);
567
568 if (buf != sbuf)
569 pfree(buf);
570
571 return result;
572}
#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 582 of file pg_locale_libc.c.

584{
585 char sbuf[TEXTBUFLEN];
586 char *buf = sbuf;
587 size_t bufsize = srclen + 1;
588 size_t result;
589
590 Assert(locale->provider == COLLPROVIDER_LIBC);
591
592 if (srclen == -1)
593 return strxfrm_l(dest, src, destsize, locale->info.lt);
594
595 if (bufsize > TEXTBUFLEN)
596 buf = palloc(bufsize);
597
598 /* nul-terminate argument */
599 memcpy(buf, src, srclen);
600 buf[srclen] = '\0';
601
602 result = strxfrm_l(dest, buf, destsize, locale->info.lt);
603
604 if (buf != sbuf)
605 pfree(buf);
606
607 /* if dest is defined, it should be nul-terminated */
608 Assert(result >= destsize || dest[result] == '\0');
609
610 return result;
611}
#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().

◆ strtitle_builtin()

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

Definition at line 84 of file pg_locale_builtin.c.

86{
87 struct WordBoundaryState wbstate = {
88 .str = src,
89 .len = srclen,
90 .offset = 0,
91 .init = false,
92 .prev_alnum = false,
93 };
94
95 return unicode_strtitle(dest, destsize, src, srclen,
96 initcap_wbnext, &wbstate);
97}
static size_t initcap_wbnext(void *state)
size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, WordBoundaryNext wbnext, void *wbstate)
Definition: unicode_case.c:99

References generate_unaccent_rules::dest, initcap_wbnext(), WordBoundaryState::str, and unicode_strtitle().

Referenced by pg_strtitle().

◆ strtitle_icu()

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

Referenced by pg_strtitle().

◆ strtitle_libc()

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

Definition at line 91 of file pg_locale_libc.c.

93{
95 return strtitle_libc_mb(dst, dstsize, src, srclen, locale);
96 else
97 return strtitle_libc_sb(dst, dstsize, src, srclen, locale);
98}
static size_t strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static size_t strtitle_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, pg_database_encoding_max_length(), strtitle_libc_mb(), and strtitle_libc_sb().

Referenced by pg_strtitle().

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 496 of file pg_locale.c.

497{
498 if (s->decimal_point == NULL)
499 return false;
500 if (s->thousands_sep == NULL)
501 return false;
502 if (s->grouping == NULL)
503 return false;
504 if (s->int_curr_symbol == NULL)
505 return false;
506 if (s->currency_symbol == NULL)
507 return false;
508 if (s->mon_decimal_point == NULL)
509 return false;
510 if (s->mon_thousands_sep == NULL)
511 return false;
512 if (s->mon_grouping == NULL)
513 return false;
514 if (s->positive_sign == NULL)
515 return false;
516 if (s->negative_sign == NULL)
517 return false;
518 return true;
519}

Referenced by PGLC_localeconv().

◆ strupper_builtin()

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

Definition at line 100 of file pg_locale_builtin.c.

102{
103 return unicode_strupper(dest, destsize, src, srclen);
104}
size_t unicode_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen)
Definition: unicode_case.c:123

References generate_unaccent_rules::dest, and unicode_strupper().

Referenced by pg_strupper().

◆ strupper_icu()

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

Referenced by pg_strupper().

◆ strupper_libc()

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

Definition at line 101 of file pg_locale_libc.c.

103{
105 return strupper_libc_mb(dst, dstsize, src, srclen, locale);
106 else
107 return strupper_libc_sb(dst, dstsize, src, srclen, locale);
108}
static size_t strupper_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static size_t strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)

References locale, pg_database_encoding_max_length(), strupper_libc_mb(), and strupper_libc_sb().

Referenced by pg_strupper().

Variable Documentation

◆ CollationCache

collation_cache_hash* CollationCache = NULL
static

Definition at line 195 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ CollationCacheContext

MemoryContext CollationCacheContext = NULL
static

Definition at line 194 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 167 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 166 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 161 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 163 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 146 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 202 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 201 of file pg_locale.c.

Referenced by pg_newlocale_from_collation().

◆ locale_messages

char* locale_messages

Definition at line 141 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 142 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 143 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 144 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 155 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 157 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 156 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 158 of file pg_locale.c.

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