PostgreSQL Source Code  git master
pg_locale.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pg_locale_struct
 

Macros

#define LOCALE_NAME_BUFLEN   128
 

Typedefs

typedef struct pg_locale_structpg_locale_t
 

Functions

bool check_locale (int category, const char *locale, char **canonname)
 
char * pg_perm_setlocale (int category, const char *locale)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
struct lconv * PGLC_localeconv (void)
 
void cache_locale_time (void)
 
void make_icu_collator (const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
 
bool pg_locale_deterministic (pg_locale_t locale)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_actual_version (char collprovider, const char *collcollate)
 
int pg_strcoll (const char *arg1, const char *arg2, pg_locale_t locale)
 
int pg_strncoll (const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
 
bool pg_strxfrm_enabled (pg_locale_t locale)
 
size_t pg_strxfrm (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
size_t pg_strnxfrm (char *dest, size_t destsize, const char *src, size_t srclen, pg_locale_t locale)
 
bool pg_strxfrm_prefix_enabled (pg_locale_t locale)
 
size_t pg_strxfrm_prefix (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
size_t pg_strnxfrm_prefix (char *dest, size_t destsize, const char *src, size_t srclen, pg_locale_t locale)
 
void icu_validate_locale (const char *loc_str)
 
char * icu_language_tag (const char *loc_str, int elevel)
 
size_t wchar2char (char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
 
size_t char2wchar (wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
 

Variables

PGDLLIMPORT char * locale_messages
 
PGDLLIMPORT char * locale_monetary
 
PGDLLIMPORT char * locale_numeric
 
PGDLLIMPORT char * locale_time
 
PGDLLIMPORT int icu_validation_level
 
PGDLLIMPORT char * localized_abbrev_days []
 
PGDLLIMPORT char * localized_full_days []
 
PGDLLIMPORT char * localized_abbrev_months []
 
PGDLLIMPORT char * localized_full_months []
 
PGDLLIMPORT bool database_ctype_is_c
 
PGDLLIMPORT struct pg_locale_struct default_locale
 

Macro Definition Documentation

◆ LOCALE_NAME_BUFLEN

#define LOCALE_NAME_BUFLEN   128

Definition at line 36 of file pg_locale.h.

Typedef Documentation

◆ pg_locale_t

typedef struct pg_locale_struct* pg_locale_t

Definition at line 90 of file pg_locale.h.

Function Documentation

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 807 of file pg_locale.c.

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

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

Referenced by DCH_from_char(), and DCH_to_char().

◆ char2wchar()

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

Definition at line 2990 of file pg_locale.c.

2992 {
2993  size_t result;
2994 
2995  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2996 
2997  if (tolen == 0)
2998  return 0;
2999 
3000 #ifdef WIN32
3001  /* See WIN32 "Unicode" comment above */
3002  if (GetDatabaseEncoding() == PG_UTF8)
3003  {
3004  /* Win32 API does not work for zero-length input */
3005  if (fromlen == 0)
3006  result = 0;
3007  else
3008  {
3009  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
3010  /* A zero return is failure */
3011  if (result == 0)
3012  result = -1;
3013  }
3014 
3015  if (result != -1)
3016  {
3017  Assert(result < tolen);
3018  /* Append trailing null wchar (MultiByteToWideChar() does not) */
3019  to[result] = 0;
3020  }
3021  }
3022  else
3023 #endif /* WIN32 */
3024  {
3025  /* mbstowcs requires ending '\0' */
3026  char *str = pnstrdup(from, fromlen);
3027 
3028  if (locale == (pg_locale_t) 0)
3029  {
3030  /* Use mbstowcs directly for the default locale */
3031  result = mbstowcs(to, str, tolen);
3032  }
3033  else
3034  {
3035  /* Use mbstowcs_l for nondefault locales */
3036  result = mbstowcs_l(to, str, tolen, locale->info.lt);
3037  }
3038 
3039  pfree(str);
3040  }
3041 
3042  if (result == -1)
3043  {
3044  /*
3045  * Invalid multibyte character encountered. We try to give a useful
3046  * error message by letting pg_verifymbstr check the string. But it's
3047  * possible that the string is OK to us, and not OK to mbstowcs ---
3048  * this suggests that the LC_CTYPE locale is different from the
3049  * database encoding. Give a generic error message if pg_verifymbstr
3050  * can't find anything wrong.
3051  */
3052  pg_verifymbstr(from, fromlen, false); /* might not return */
3053  /* but if it does ... */
3054  ereport(ERROR,
3055  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
3056  errmsg("invalid multibyte character for locale"),
3057  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
3058  }
3059 
3060  return result;
3061 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
static char * locale
Definition: initdb.c:140
Assert(fmt[strlen(fmt) - 1] !='\n')
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1563
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1655
static size_t mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc)
Definition: pg_locale.c:167

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

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

◆ check_locale()

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

Definition at line 316 of file pg_locale.c.

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

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

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

◆ get_collation_actual_version()

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

Definition at line 1677 of file pg_locale.c.

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

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

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

◆ icu_language_tag()

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

Definition at line 2796 of file pg_locale.c.

2797 {
2798 #ifdef USE_ICU
2799  UErrorCode status;
2800  char *langtag;
2801  size_t buflen = 32; /* arbitrary starting buffer size */
2802  const bool strict = true;
2803 
2804  /*
2805  * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
2806  * RFC5646 section 4.4). Additionally, in older ICU versions,
2807  * uloc_toLanguageTag() doesn't always return the ultimate length on the
2808  * first call, necessitating a loop.
2809  */
2810  langtag = palloc(buflen);
2811  while (true)
2812  {
2813  status = U_ZERO_ERROR;
2814  uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
2815 
2816  /* try again if the buffer is not large enough */
2817  if ((status == U_BUFFER_OVERFLOW_ERROR ||
2818  status == U_STRING_NOT_TERMINATED_WARNING) &&
2819  buflen < MaxAllocSize)
2820  {
2821  buflen = Min(buflen * 2, MaxAllocSize);
2822  langtag = repalloc(langtag, buflen);
2823  continue;
2824  }
2825 
2826  break;
2827  }
2828 
2829  if (U_FAILURE(status))
2830  {
2831  pfree(langtag);
2832 
2833  if (elevel > 0)
2834  ereport(elevel,
2835  (errmsg("could not convert locale name \"%s\" to language tag: %s",
2836  loc_str, u_errorName(status))));
2837  return NULL;
2838  }
2839 
2840  return langtag;
2841 #else /* not USE_ICU */
2842  ereport(ERROR,
2843  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2844  errmsg("ICU is not supported in this build")));
2845  return NULL; /* keep compiler quiet */
2846 #endif /* not USE_ICU */
2847 }
#define Min(x, y)
Definition: c.h:993
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * palloc(Size size)
Definition: mcxt.c:1226
#define MaxAllocSize
Definition: memutils.h:40

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

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

◆ icu_validate_locale()

void icu_validate_locale ( const char *  loc_str)

Definition at line 2853 of file pg_locale.c.

2854 {
2855 #ifdef USE_ICU
2856  UCollator *collator;
2857  UErrorCode status;
2858  char lang[ULOC_LANG_CAPACITY];
2859  bool found = false;
2860  int elevel = icu_validation_level;
2861 
2862  /* no validation */
2863  if (elevel < 0)
2864  return;
2865 
2866  /* downgrade to WARNING during pg_upgrade */
2867  if (IsBinaryUpgrade && elevel > WARNING)
2868  elevel = WARNING;
2869 
2870  /* validate that we can extract the language */
2871  status = U_ZERO_ERROR;
2872  uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
2873  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2874  {
2875  ereport(elevel,
2876  (errmsg("could not get language from ICU locale \"%s\": %s",
2877  loc_str, u_errorName(status)),
2878  errhint("To disable ICU locale validation, set the parameter %s to \"%s\".",
2879  "icu_validation_level", "disabled")));
2880  return;
2881  }
2882 
2883  /* check for special language name */
2884  if (strcmp(lang, "") == 0 ||
2885  strcmp(lang, "root") == 0 || strcmp(lang, "und") == 0)
2886  found = true;
2887 
2888  /* search for matching language within ICU */
2889  for (int32_t i = 0; !found && i < uloc_countAvailable(); i++)
2890  {
2891  const char *otherloc = uloc_getAvailable(i);
2892  char otherlang[ULOC_LANG_CAPACITY];
2893 
2894  status = U_ZERO_ERROR;
2895  uloc_getLanguage(otherloc, otherlang, ULOC_LANG_CAPACITY, &status);
2896  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2897  continue;
2898 
2899  if (strcmp(lang, otherlang) == 0)
2900  found = true;
2901  }
2902 
2903  if (!found)
2904  ereport(elevel,
2905  (errmsg("ICU locale \"%s\" has unknown language \"%s\"",
2906  loc_str, lang),
2907  errhint("To disable ICU locale validation, set the parameter %s to \"%s\".",
2908  "icu_validation_level", "disabled")));
2909 
2910  /* check that it can be opened */
2911  collator = pg_ucol_open(loc_str);
2912  ucol_close(collator);
2913 #else /* not USE_ICU */
2914  /* could get here if a collation was created by a build with ICU */
2915  ereport(ERROR,
2916  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2917  errmsg("ICU is not supported in this build")));
2918 #endif /* not USE_ICU */
2919 }
bool IsBinaryUpgrade
Definition: globals.c:116
int icu_validation_level
Definition: pg_locale.c:103

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

Referenced by createdb(), and DefineCollation().

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1307 of file pg_locale.c.

1308 {
1309  /*
1310  * If we're asked about "collation 0", return false, so that the code will
1311  * go into the non-C path and report that the collation is bogus.
1312  */
1313  if (!OidIsValid(collation))
1314  return false;
1315 
1316  /*
1317  * If we're asked about the default collation, we have to inquire of the C
1318  * library. Cache the result so we only have to compute it once.
1319  */
1320  if (collation == DEFAULT_COLLATION_OID)
1321  {
1322  static int result = -1;
1323  char *localeptr;
1324 
1325  if (default_locale.provider == COLLPROVIDER_ICU)
1326  return false;
1327 
1328  if (result >= 0)
1329  return (bool) result;
1330  localeptr = setlocale(LC_COLLATE, NULL);
1331  if (!localeptr)
1332  elog(ERROR, "invalid LC_COLLATE setting");
1333 
1334  if (strcmp(localeptr, "C") == 0)
1335  result = true;
1336  else if (strcmp(localeptr, "POSIX") == 0)
1337  result = true;
1338  else
1339  result = false;
1340  return (bool) result;
1341  }
1342 
1343  /*
1344  * If we're asked about the built-in C/POSIX collations, we know that.
1345  */
1346  if (collation == C_COLLATION_OID ||
1347  collation == POSIX_COLLATION_OID)
1348  return true;
1349 
1350  /*
1351  * Otherwise, we have to consult pg_collation, but we cache that.
1352  */
1353  return (lookup_collation_cache(collation, true))->collate_is_c;
1354 }
#define OidIsValid(objectId)
Definition: c.h:764
struct pg_locale_struct default_locale
Definition: pg_locale.c:1409
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1231

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

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

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1360 of file pg_locale.c.

1361 {
1362  /*
1363  * If we're asked about "collation 0", return false, so that the code will
1364  * go into the non-C path and report that the collation is bogus.
1365  */
1366  if (!OidIsValid(collation))
1367  return false;
1368 
1369  /*
1370  * If we're asked about the default collation, we have to inquire of the C
1371  * library. Cache the result so we only have to compute it once.
1372  */
1373  if (collation == DEFAULT_COLLATION_OID)
1374  {
1375  static int result = -1;
1376  char *localeptr;
1377 
1378  if (default_locale.provider == COLLPROVIDER_ICU)
1379  return false;
1380 
1381  if (result >= 0)
1382  return (bool) result;
1383  localeptr = setlocale(LC_CTYPE, NULL);
1384  if (!localeptr)
1385  elog(ERROR, "invalid LC_CTYPE setting");
1386 
1387  if (strcmp(localeptr, "C") == 0)
1388  result = true;
1389  else if (strcmp(localeptr, "POSIX") == 0)
1390  result = true;
1391  else
1392  result = false;
1393  return (bool) result;
1394  }
1395 
1396  /*
1397  * If we're asked about the built-in C/POSIX collations, we know that.
1398  */
1399  if (collation == C_COLLATION_OID ||
1400  collation == POSIX_COLLATION_OID)
1401  return true;
1402 
1403  /*
1404  * Otherwise, we have to consult pg_collation, but we cache that.
1405  */
1406  return (lookup_collation_cache(collation, true))->ctype_is_c;
1407 }

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

◆ make_icu_collator()

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

Definition at line 1412 of file pg_locale.c.

1415 {
1416 #ifdef USE_ICU
1417  UCollator *collator;
1418 
1419  collator = pg_ucol_open(iculocstr);
1420 
1421  /*
1422  * If rules are specified, we extract the rules of the standard collation,
1423  * add our own rules, and make a new collator with the combined rules.
1424  */
1425  if (icurules)
1426  {
1427  const UChar *default_rules;
1428  UChar *agg_rules;
1429  UChar *my_rules;
1430  UErrorCode status;
1431  int32_t length;
1432 
1433  default_rules = ucol_getRules(collator, &length);
1434  icu_to_uchar(&my_rules, icurules, strlen(icurules));
1435 
1436  agg_rules = palloc_array(UChar, u_strlen(default_rules) + u_strlen(my_rules) + 1);
1437  u_strcpy(agg_rules, default_rules);
1438  u_strcat(agg_rules, my_rules);
1439 
1440  ucol_close(collator);
1441 
1442  status = U_ZERO_ERROR;
1443  collator = ucol_openRules(agg_rules, u_strlen(agg_rules),
1444  UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
1445  if (U_FAILURE(status))
1446  ereport(ERROR,
1447  (errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s",
1448  iculocstr, icurules, u_errorName(status))));
1449  }
1450 
1451  /* We will leak this string if the caller errors later :-( */
1452  resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1453  resultp->info.icu.ucol = collator;
1454 #else /* not USE_ICU */
1455  /* could get here if a collation was created by a build with ICU */
1456  ereport(ERROR,
1457  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1458  errmsg("ICU is not supported in this build")));
1459 #endif /* not USE_ICU */
1460 }
#define palloc_array(type, count)
Definition: fe_memutils.h:64
MemoryContext TopMemoryContext
Definition: mcxt.c:141
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1631
union pg_locale_struct::@145 info

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

Referenced by CheckMyDatabase(), and pg_newlocale_from_collation().

◆ pg_locale_deterministic()

bool pg_locale_deterministic ( pg_locale_t  locale)

Definition at line 1494 of file pg_locale.c.

1495 {
1496  /* default locale must always be deterministic */
1497  if (locale == NULL)
1498  return true;
1499  else
1500  return locale->deterministic;
1501 }

References locale.

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

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1514 of file pg_locale.c.

1515 {
1516  collation_cache_entry *cache_entry;
1517 
1518  /* Callers must pass a valid OID */
1520 
1521  if (collid == DEFAULT_COLLATION_OID)
1522  {
1523  if (default_locale.provider == COLLPROVIDER_ICU)
1524  return &default_locale;
1525  else
1526  return (pg_locale_t) 0;
1527  }
1528 
1529  cache_entry = lookup_collation_cache(collid, false);
1530 
1531  if (cache_entry->locale == 0)
1532  {
1533  /* We haven't computed this yet in this session, so do it */
1534  HeapTuple tp;
1535  Form_pg_collation collform;
1536  struct pg_locale_struct result;
1537  pg_locale_t resultp;
1538  Datum datum;
1539  bool isnull;
1540 
1542  if (!HeapTupleIsValid(tp))
1543  elog(ERROR, "cache lookup failed for collation %u", collid);
1544  collform = (Form_pg_collation) GETSTRUCT(tp);
1545 
1546  /* We'll fill in the result struct locally before allocating memory */
1547  memset(&result, 0, sizeof(result));
1548  result.provider = collform->collprovider;
1549  result.deterministic = collform->collisdeterministic;
1550 
1551  if (collform->collprovider == COLLPROVIDER_LIBC)
1552  {
1553  const char *collcollate;
1554  const char *collctype pg_attribute_unused();
1555  locale_t loc;
1556 
1557  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1558  collcollate = TextDatumGetCString(datum);
1559  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1560  collctype = TextDatumGetCString(datum);
1561 
1562  if (strcmp(collcollate, collctype) == 0)
1563  {
1564  /* Normal case where they're the same */
1565  errno = 0;
1566 #ifndef WIN32
1567  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1568  NULL);
1569 #else
1570  loc = _create_locale(LC_ALL, collcollate);
1571 #endif
1572  if (!loc)
1573  report_newlocale_failure(collcollate);
1574  }
1575  else
1576  {
1577 #ifndef WIN32
1578  /* We need two newlocale() steps */
1579  locale_t loc1;
1580 
1581  errno = 0;
1582  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1583  if (!loc1)
1584  report_newlocale_failure(collcollate);
1585  errno = 0;
1586  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1587  if (!loc)
1588  report_newlocale_failure(collctype);
1589 #else
1590 
1591  /*
1592  * XXX The _create_locale() API doesn't appear to support
1593  * this. Could perhaps be worked around by changing
1594  * pg_locale_t to contain two separate fields.
1595  */
1596  ereport(ERROR,
1597  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1598  errmsg("collations with different collate and ctype values are not supported on this platform")));
1599 #endif
1600  }
1601 
1602  result.info.lt = loc;
1603  }
1604  else if (collform->collprovider == COLLPROVIDER_ICU)
1605  {
1606  const char *iculocstr;
1607  const char *icurules;
1608 
1609  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colliculocale);
1610  iculocstr = TextDatumGetCString(datum);
1611 
1612  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1613  if (!isnull)
1614  icurules = TextDatumGetCString(datum);
1615  else
1616  icurules = NULL;
1617 
1618  make_icu_collator(iculocstr, icurules, &result);
1619  }
1620 
1621  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1622  &isnull);
1623  if (!isnull)
1624  {
1625  char *actual_versionstr;
1626  char *collversionstr;
1627 
1628  collversionstr = TextDatumGetCString(datum);
1629 
1630  datum = SysCacheGetAttrNotNull(COLLOID, tp, collform->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate);
1631 
1632  actual_versionstr = get_collation_actual_version(collform->collprovider,
1633  TextDatumGetCString(datum));
1634  if (!actual_versionstr)
1635  {
1636  /*
1637  * This could happen when specifying a version in CREATE
1638  * COLLATION but the provider does not support versioning, or
1639  * manually creating a mess in the catalogs.
1640  */
1641  ereport(ERROR,
1642  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1643  NameStr(collform->collname))));
1644  }
1645 
1646  if (strcmp(actual_versionstr, collversionstr) != 0)
1647  ereport(WARNING,
1648  (errmsg("collation \"%s\" has version mismatch",
1649  NameStr(collform->collname)),
1650  errdetail("The collation in the database was created using version %s, "
1651  "but the operating system provides version %s.",
1652  collversionstr, actual_versionstr),
1653  errhint("Rebuild all objects affected by this collation and run "
1654  "ALTER COLLATION %s REFRESH VERSION, "
1655  "or build PostgreSQL with the right library version.",
1656  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1657  NameStr(collform->collname)))));
1658  }
1659 
1660  ReleaseSysCache(tp);
1661 
1662  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1663  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1664  *resultp = result;
1665 
1666  cache_entry->locale = resultp;
1667  }
1668 
1669  return cache_entry->locale;
1670 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:735
#define pg_attribute_unused()
Definition: c.h:125
Oid collid
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3348
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1412
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1677
static void report_newlocale_failure(const char *localename)
Definition: pg_locale.c:1465
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12059
Definition: pg_locale.c:127
pg_locale_t locale
Definition: pg_locale.c:132
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1081
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1112
@ COLLOID
Definition: syscache.h:50

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

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

◆ pg_perm_setlocale()

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

Definition at line 213 of file pg_locale.c.

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

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

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

◆ pg_strcoll()

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

Definition at line 2026 of file pg_locale.c.

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

References locale, pg_strcoll_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by varstrfastcmp_locale().

◆ pg_strncoll()

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

Definition at line 2061 of file pg_locale.c.

2063 {
2064  int result;
2065 
2066  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2067  result = pg_strncoll_libc(arg1, len1, arg2, len2, locale);
2068 #ifdef USE_ICU
2069  else if (locale->provider == COLLPROVIDER_ICU)
2070  result = pg_strncoll_icu(arg1, len1, arg2, len2, locale);
2071 #endif
2072  else
2073  /* shouldn't happen */
2074  PGLOCALE_SUPPORT_ERROR(locale->provider);
2075 
2076  return result;
2077 }
static int pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
Definition: pg_locale.c:1873

References locale, pg_strncoll_libc(), and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_cmp().

◆ pg_strnxfrm()

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

Definition at line 2345 of file pg_locale.c.

2347 {
2348  size_t result = 0; /* keep compiler quiet */
2349 
2350  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2351  result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale);
2352 #ifdef USE_ICU
2353  else if (locale->provider == COLLPROVIDER_ICU)
2354  result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale);
2355 #endif
2356  else
2357  /* shouldn't happen */
2358  PGLOCALE_SUPPORT_ERROR(locale->provider);
2359 
2360  return result;
2361 }
static size_t pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2099

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

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

◆ pg_strnxfrm_prefix()

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

Definition at line 2430 of file pg_locale.c.

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

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

◆ pg_strxfrm()

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

Definition at line 2309 of file pg_locale.c.

2310 {
2311  size_t result = 0; /* keep compiler quiet */
2312 
2313  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2314  result = pg_strxfrm_libc(dest, src, destsize, locale);
2315 #ifdef USE_ICU
2316  else if (locale->provider == COLLPROVIDER_ICU)
2317  result = pg_strnxfrm_icu(dest, src, -1, destsize, locale);
2318 #endif
2319  else
2320  /* shouldn't happen */
2321  PGLOCALE_SUPPORT_ERROR(locale->provider);
2322 
2323  return result;
2324 }
static size_t pg_strxfrm_libc(char *dest, const char *src, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2081

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

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 2277 of file pg_locale.c.

2278 {
2279  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2280 #ifdef TRUST_STRXFRM
2281  return true;
2282 #else
2283  return false;
2284 #endif
2285  else if (locale->provider == COLLPROVIDER_ICU)
2286  return true;
2287  else
2288  /* shouldn't happen */
2289  PGLOCALE_SUPPORT_ERROR(locale->provider);
2290 
2291  return false; /* keep compiler quiet */
2292 }

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

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

References generate_unaccent_rules::dest, locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_prefix_enabled()

bool pg_strxfrm_prefix_enabled ( pg_locale_t  locale)

Definition at line 2368 of file pg_locale.c.

2369 {
2370  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2371  return false;
2372  else if (locale->provider == COLLPROVIDER_ICU)
2373  return true;
2374  else
2375  /* shouldn't happen */
2376  PGLOCALE_SUPPORT_ERROR(locale->provider);
2377 
2378  return false; /* keep compiler quiet */
2379 }

References locale, and PGLOCALE_SUPPORT_ERROR.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 525 of file pg_locale.c.

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

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

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

◆ wchar2char()

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

Definition at line 2934 of file pg_locale.c.

2935 {
2936  size_t result;
2937 
2938  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2939 
2940  if (tolen == 0)
2941  return 0;
2942 
2943 #ifdef WIN32
2944 
2945  /*
2946  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
2947  * for some reason mbstowcs and wcstombs won't do this for us, so we use
2948  * MultiByteToWideChar().
2949  */
2950  if (GetDatabaseEncoding() == PG_UTF8)
2951  {
2952  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
2953  NULL, NULL);
2954  /* A zero return is failure */
2955  if (result <= 0)
2956  result = -1;
2957  else
2958  {
2959  Assert(result <= tolen);
2960  /* Microsoft counts the zero terminator in the result */
2961  result--;
2962  }
2963  }
2964  else
2965 #endif /* WIN32 */
2966  if (locale == (pg_locale_t) 0)
2967  {
2968  /* Use wcstombs directly for the default locale */
2969  result = wcstombs(to, from, tolen);
2970  }
2971  else
2972  {
2973  /* Use wcstombs_l for nondefault locales */
2974  result = wcstombs_l(to, from, tolen, locale->info.lt);
2975  }
2976 
2977  return result;
2978 }
static size_t wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc)
Definition: pg_locale.c:183

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

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

Variable Documentation

◆ database_ctype_is_c

PGDLLIMPORT bool database_ctype_is_c
extern

◆ default_locale

PGDLLIMPORT struct pg_locale_struct default_locale
extern

Definition at line 1360 of file pg_locale.c.

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

◆ icu_validation_level

PGDLLIMPORT int icu_validation_level
extern

Definition at line 103 of file pg_locale.c.

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

◆ locale_messages

PGDLLIMPORT char* locale_messages
extern

Definition at line 98 of file pg_locale.c.

◆ locale_monetary

PGDLLIMPORT char* locale_monetary
extern

Definition at line 99 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

PGDLLIMPORT char* locale_numeric
extern

Definition at line 100 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

PGDLLIMPORT char* locale_time
extern

Definition at line 101 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

PGDLLIMPORT char* localized_abbrev_days[]
extern

Definition at line 112 of file pg_locale.c.

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

◆ localized_abbrev_months

PGDLLIMPORT char* localized_abbrev_months[]
extern

Definition at line 114 of file pg_locale.c.

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

◆ localized_full_days

PGDLLIMPORT char* localized_full_days[]
extern

Definition at line 113 of file pg_locale.c.

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

◆ localized_full_months

PGDLLIMPORT char* localized_full_months[]
extern

Definition at line 115 of file pg_locale.c.

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