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 95 of file pg_locale.h.

Function Documentation

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 766 of file pg_locale.c.

767 {
768  char buf[(2 * 7 + 2 * 12) * MAX_L10N_DATA];
769  char *bufptr;
770  time_t timenow;
771  struct tm *timeinfo;
772  bool strftimefail = false;
773  int encoding;
774  int i;
775  char *save_lc_time;
776 #ifdef WIN32
777  char *save_lc_ctype;
778 #endif
779 
780  /* did we do this already? */
781  if (CurrentLCTimeValid)
782  return;
783 
784  elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
785 
786  /*
787  * As in PGLC_localeconv(), it's critical that we not throw error while
788  * libc's locale settings have nondefault values. Hence, we just call
789  * strftime() within the critical section, and then convert and save its
790  * results afterwards.
791  */
792 
793  /* Save prevailing value of time locale */
794  save_lc_time = setlocale(LC_TIME, NULL);
795  if (!save_lc_time)
796  elog(ERROR, "setlocale(NULL) failed");
797  save_lc_time = pstrdup(save_lc_time);
798 
799 #ifdef WIN32
800 
801  /*
802  * On Windows, it appears that wcsftime() internally uses LC_CTYPE, so we
803  * must set it here. This code looks the same as what PGLC_localeconv()
804  * does, but the underlying reason is different: this does NOT determine
805  * the encoding we'll get back from strftime_win32().
806  */
807 
808  /* Save prevailing value of ctype locale */
809  save_lc_ctype = setlocale(LC_CTYPE, NULL);
810  if (!save_lc_ctype)
811  elog(ERROR, "setlocale(NULL) failed");
812  save_lc_ctype = pstrdup(save_lc_ctype);
813 
814  /* use lc_time to set the ctype */
815  setlocale(LC_CTYPE, locale_time);
816 #endif
817 
818  setlocale(LC_TIME, locale_time);
819 
820  /* We use times close to current time as data for strftime(). */
821  timenow = time(NULL);
822  timeinfo = localtime(&timenow);
823 
824  /* Store the strftime results in MAX_L10N_DATA-sized portions of buf[] */
825  bufptr = buf;
826 
827  /*
828  * MAX_L10N_DATA is sufficient buffer space for every known locale, and
829  * POSIX defines no strftime() errors. (Buffer space exhaustion is not an
830  * error.) An implementation might report errors (e.g. ENOMEM) by
831  * returning 0 (or, less plausibly, a negative value) and setting errno.
832  * Report errno just in case the implementation did that, but clear it in
833  * advance of the calls so we don't emit a stale, unrelated errno.
834  */
835  errno = 0;
836 
837  /* localized days */
838  for (i = 0; i < 7; i++)
839  {
840  timeinfo->tm_wday = i;
841  if (strftime(bufptr, MAX_L10N_DATA, "%a", timeinfo) <= 0)
842  strftimefail = true;
843  bufptr += MAX_L10N_DATA;
844  if (strftime(bufptr, MAX_L10N_DATA, "%A", timeinfo) <= 0)
845  strftimefail = true;
846  bufptr += MAX_L10N_DATA;
847  }
848 
849  /* localized months */
850  for (i = 0; i < 12; i++)
851  {
852  timeinfo->tm_mon = i;
853  timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
854  if (strftime(bufptr, MAX_L10N_DATA, "%b", timeinfo) <= 0)
855  strftimefail = true;
856  bufptr += MAX_L10N_DATA;
857  if (strftime(bufptr, MAX_L10N_DATA, "%B", timeinfo) <= 0)
858  strftimefail = true;
859  bufptr += MAX_L10N_DATA;
860  }
861 
862  /*
863  * Restore the prevailing locale settings; as in PGLC_localeconv(),
864  * failure to do so is fatal.
865  */
866 #ifdef WIN32
867  if (!setlocale(LC_CTYPE, save_lc_ctype))
868  elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype);
869 #endif
870  if (!setlocale(LC_TIME, save_lc_time))
871  elog(FATAL, "failed to restore LC_TIME to \"%s\"", save_lc_time);
872 
873  /*
874  * At this point we've done our best to clean up, and can throw errors, or
875  * call functions that might throw errors, with a clean conscience.
876  */
877  if (strftimefail)
878  elog(ERROR, "strftime() failed: %m");
879 
880  /* Release the pstrdup'd locale names */
881  pfree(save_lc_time);
882 #ifdef WIN32
883  pfree(save_lc_ctype);
884 #endif
885 
886 #ifndef WIN32
887 
888  /*
889  * As in PGLC_localeconv(), we must convert strftime()'s output from the
890  * encoding implied by LC_TIME to the database encoding. If we can't
891  * identify the LC_TIME encoding, just perform encoding validation.
892  */
894  if (encoding < 0)
896 
897 #else
898 
899  /*
900  * On Windows, strftime_win32() always returns UTF8 data, so convert from
901  * that if necessary.
902  */
903  encoding = PG_UTF8;
904 
905 #endif /* WIN32 */
906 
907  bufptr = buf;
908 
909  /* localized days */
910  for (i = 0; i < 7; i++)
911  {
913  bufptr += MAX_L10N_DATA;
915  bufptr += MAX_L10N_DATA;
916  }
917  localized_abbrev_days[7] = NULL;
918  localized_full_days[7] = NULL;
919 
920  /* localized months */
921  for (i = 0; i < 12; i++)
922  {
924  bufptr += MAX_L10N_DATA;
926  bufptr += MAX_L10N_DATA;
927  }
928  localized_abbrev_months[12] = NULL;
929  localized_full_months[12] = NULL;
930 
931  CurrentLCTimeValid = true;
932 }
#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:111
static bool CurrentLCTimeValid
Definition: pg_locale.c:118
char * locale_time
Definition: pg_locale.c:97
static void cache_single_string(char **dst, const char *src, int encoding)
Definition: pg_locale.c:743
#define MAX_L10N_DATA
Definition: pg_locale.c:90
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:110
char * localized_full_days[7+1]
Definition: pg_locale.c:109
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:108
static char * buf
Definition: pg_test_fsync.c:67
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
@ PG_UTF8
Definition: pg_wchar.h:232
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:428
#define setlocale(a, b)
Definition: win32_port.h:477

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

3009 {
3010  size_t result;
3011 
3012  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
3013 
3014  if (tolen == 0)
3015  return 0;
3016 
3017 #ifdef WIN32
3018  /* See WIN32 "Unicode" comment above */
3019  if (GetDatabaseEncoding() == PG_UTF8)
3020  {
3021  /* Win32 API does not work for zero-length input */
3022  if (fromlen == 0)
3023  result = 0;
3024  else
3025  {
3026  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
3027  /* A zero return is failure */
3028  if (result == 0)
3029  result = -1;
3030  }
3031 
3032  if (result != -1)
3033  {
3034  Assert(result < tolen);
3035  /* Append trailing null wchar (MultiByteToWideChar() does not) */
3036  to[result] = 0;
3037  }
3038  }
3039  else
3040 #endif /* WIN32 */
3041  {
3042  /* mbstowcs requires ending '\0' */
3043  char *str = pnstrdup(from, fromlen);
3044 
3045  if (locale == (pg_locale_t) 0)
3046  {
3047  /* Use mbstowcs directly for the default locale */
3048  result = mbstowcs(to, str, tolen);
3049  }
3050  else
3051  {
3052 #ifdef HAVE_LOCALE_T
3053 #ifdef HAVE_MBSTOWCS_L
3054  /* Use mbstowcs_l for nondefault locales */
3055  result = mbstowcs_l(to, str, tolen, locale->info.lt);
3056 #else /* !HAVE_MBSTOWCS_L */
3057  /* We have to temporarily set the locale as current ... ugh */
3058  locale_t save_locale = uselocale(locale->info.lt);
3059 
3060  result = mbstowcs(to, str, tolen);
3061 
3062  uselocale(save_locale);
3063 #endif /* HAVE_MBSTOWCS_L */
3064 #else /* !HAVE_LOCALE_T */
3065  /* Can't have locale != 0 without HAVE_LOCALE_T */
3066  elog(ERROR, "mbstowcs_l is not available");
3067  result = 0; /* keep compiler quiet */
3068 #endif /* HAVE_LOCALE_T */
3069  }
3070 
3071  pfree(str);
3072  }
3073 
3074  if (result == -1)
3075  {
3076  /*
3077  * Invalid multibyte character encountered. We try to give a useful
3078  * error message by letting pg_verifymbstr check the string. But it's
3079  * possible that the string is OK to us, and not OK to mbstowcs ---
3080  * this suggests that the LC_CTYPE locale is different from the
3081  * database encoding. Give a generic error message if pg_verifymbstr
3082  * can't find anything wrong.
3083  */
3084  pg_verifymbstr(from, fromlen, false); /* might not return */
3085  /* but if it does ... */
3086  ereport(ERROR,
3087  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
3088  errmsg("invalid multibyte character for locale"),
3089  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
3090  }
3091 
3092  return result;
3093 }
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:139
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
#define locale_t
Definition: win32_port.h:432
#define mbstowcs_l
Definition: win32_port.h:459

References Assert(), elog(), ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), locale, locale_t, 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 275 of file pg_locale.c.

276 {
277  char *save;
278  char *res;
279 
280  if (canonname)
281  *canonname = NULL; /* in case of failure */
282 
283  save = setlocale(category, NULL);
284  if (!save)
285  return false; /* won't happen, we hope */
286 
287  /* save may be pointing at a modifiable scratch variable, see above. */
288  save = pstrdup(save);
289 
290  /* set the locale with setlocale, to see if it accepts it. */
291  res = setlocale(category, locale);
292 
293  /* save canonical name if requested. */
294  if (res && canonname)
295  *canonname = pstrdup(res);
296 
297  /* restore old value. */
298  if (!setlocale(category, save))
299  elog(WARNING, "failed to restore old locale \"%s\"", save);
300  pfree(save);
301 
302  return (res != NULL);
303 }
#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 1649 of file pg_locale.c.

1650 {
1651  char *collversion = NULL;
1652 
1653 #ifdef USE_ICU
1654  if (collprovider == COLLPROVIDER_ICU)
1655  {
1656  UCollator *collator;
1657  UVersionInfo versioninfo;
1658  char buf[U_MAX_VERSION_STRING_LENGTH];
1659 
1660  collator = pg_ucol_open(collcollate);
1661 
1662  ucol_getVersion(collator, versioninfo);
1663  ucol_close(collator);
1664 
1665  u_versionToString(versioninfo, buf);
1666  collversion = pstrdup(buf);
1667  }
1668  else
1669 #endif
1670  if (collprovider == COLLPROVIDER_LIBC &&
1671  pg_strcasecmp("C", collcollate) != 0 &&
1672  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1673  pg_strcasecmp("POSIX", collcollate) != 0)
1674  {
1675 #if defined(__GLIBC__)
1676  /* Use the glibc version because we don't have anything better. */
1677  collversion = pstrdup(gnu_get_libc_version());
1678 #elif defined(LC_VERSION_MASK)
1679  locale_t loc;
1680 
1681  /* Look up FreeBSD collation version. */
1682  loc = newlocale(LC_COLLATE, collcollate, NULL);
1683  if (loc)
1684  {
1685  collversion =
1686  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1687  freelocale(loc);
1688  }
1689  else
1690  ereport(ERROR,
1691  (errmsg("could not load locale \"%s\"", collcollate)));
1692 #elif defined(WIN32)
1693  /*
1694  * If we are targeting Windows Vista and above, we can ask for a name
1695  * given a collation name (earlier versions required a location code
1696  * that we don't have).
1697  */
1698  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1699  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1700 
1701  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1702  LOCALE_NAME_MAX_LENGTH);
1703  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1704  {
1705  /*
1706  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1707  * locale name like "English_United States.1252". Until those
1708  * values can be prevented from entering the system, or 100%
1709  * reliably converted to the more useful tag format, tolerate the
1710  * resulting error and report that we have no version data.
1711  */
1712  if (GetLastError() == ERROR_INVALID_PARAMETER)
1713  return NULL;
1714 
1715  ereport(ERROR,
1716  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1717  collcollate,
1718  GetLastError())));
1719  }
1720  collversion = psprintf("%lu.%lu,%lu.%lu",
1721  (version.dwNLSVersion >> 8) & 0xFFFF,
1722  version.dwNLSVersion & 0xFF,
1723  (version.dwDefinedVersion >> 8) & 0xFFFF,
1724  version.dwDefinedVersion & 0xFF);
1725 #endif
1726  }
1727 
1728  return collversion;
1729 }
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

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

2784 {
2785 #ifdef USE_ICU
2786  UErrorCode status;
2787  char lang[ULOC_LANG_CAPACITY];
2788  char *langtag;
2789  size_t buflen = 32; /* arbitrary starting buffer size */
2790  const bool strict = true;
2791 
2792  status = U_ZERO_ERROR;
2793  uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status);
2794  if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING)
2795  {
2796  if (elevel > 0)
2797  ereport(elevel,
2798  (errmsg("could not get language from locale \"%s\": %s",
2799  loc_str, u_errorName(status))));
2800  return NULL;
2801  }
2802 
2803  /* C/POSIX locales aren't handled by uloc_getLanguageTag() */
2804  if (strcmp(lang, "c") == 0 || strcmp(lang, "posix") == 0)
2805  return pstrdup("en-US-u-va-posix");
2806 
2807  /*
2808  * A BCP47 language tag doesn't have a clearly-defined upper limit (cf.
2809  * RFC5646 section 4.4). Additionally, in older ICU versions,
2810  * uloc_toLanguageTag() doesn't always return the ultimate length on the
2811  * first call, necessitating a loop.
2812  */
2813  langtag = palloc(buflen);
2814  while (true)
2815  {
2816  status = U_ZERO_ERROR;
2817  uloc_toLanguageTag(loc_str, langtag, buflen, strict, &status);
2818 
2819  /* try again if the buffer is not large enough */
2820  if ((status == U_BUFFER_OVERFLOW_ERROR ||
2821  status == U_STRING_NOT_TERMINATED_WARNING) &&
2822  buflen < MaxAllocSize)
2823  {
2824  buflen = Min(buflen * 2, MaxAllocSize);
2825  langtag = repalloc(langtag, buflen);
2826  continue;
2827  }
2828 
2829  break;
2830  }
2831 
2832  if (U_FAILURE(status))
2833  {
2834  pfree(langtag);
2835 
2836  if (elevel > 0)
2837  ereport(elevel,
2838  (errmsg("could not convert locale name \"%s\" to language tag: %s",
2839  loc_str, u_errorName(status))));
2840  return NULL;
2841  }
2842 
2843  return langtag;
2844 #else /* not USE_ICU */
2845  ereport(ERROR,
2846  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2847  errmsg("ICU is not supported in this build")));
2848  return NULL; /* keep compiler quiet */
2849 #endif /* not USE_ICU */
2850 }
#define Min(x, y)
Definition: c.h:988
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(), pstrdup(), 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 2856 of file pg_locale.c.

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

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

1267 {
1268  /*
1269  * If we're asked about "collation 0", return false, so that the code will
1270  * go into the non-C path and report that the collation is bogus.
1271  */
1272  if (!OidIsValid(collation))
1273  return false;
1274 
1275  /*
1276  * If we're asked about the default collation, we have to inquire of the C
1277  * library. Cache the result so we only have to compute it once.
1278  */
1279  if (collation == DEFAULT_COLLATION_OID)
1280  {
1281  static int result = -1;
1282  char *localeptr;
1283 
1284  if (default_locale.provider == COLLPROVIDER_ICU)
1285  return false;
1286 
1287  if (result >= 0)
1288  return (bool) result;
1289  localeptr = setlocale(LC_COLLATE, NULL);
1290  if (!localeptr)
1291  elog(ERROR, "invalid LC_COLLATE setting");
1292 
1293  if (strcmp(localeptr, "C") == 0)
1294  result = true;
1295  else if (strcmp(localeptr, "POSIX") == 0)
1296  result = true;
1297  else
1298  result = false;
1299  return (bool) result;
1300  }
1301 
1302  /*
1303  * If we're asked about the built-in C/POSIX collations, we know that.
1304  */
1305  if (collation == C_COLLATION_OID ||
1306  collation == POSIX_COLLATION_OID)
1307  return true;
1308 
1309  /*
1310  * Otherwise, we have to consult pg_collation, but we cache that.
1311  */
1312  return (lookup_collation_cache(collation, true))->collate_is_c;
1313 }
#define OidIsValid(objectId)
Definition: c.h:759
struct pg_locale_struct default_locale
Definition: pg_locale.c:1368
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1190

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

1320 {
1321  /*
1322  * If we're asked about "collation 0", return false, so that the code will
1323  * go into the non-C path and report that the collation is bogus.
1324  */
1325  if (!OidIsValid(collation))
1326  return false;
1327 
1328  /*
1329  * If we're asked about the default collation, we have to inquire of the C
1330  * library. Cache the result so we only have to compute it once.
1331  */
1332  if (collation == DEFAULT_COLLATION_OID)
1333  {
1334  static int result = -1;
1335  char *localeptr;
1336 
1337  if (default_locale.provider == COLLPROVIDER_ICU)
1338  return false;
1339 
1340  if (result >= 0)
1341  return (bool) result;
1342  localeptr = setlocale(LC_CTYPE, NULL);
1343  if (!localeptr)
1344  elog(ERROR, "invalid LC_CTYPE setting");
1345 
1346  if (strcmp(localeptr, "C") == 0)
1347  result = true;
1348  else if (strcmp(localeptr, "POSIX") == 0)
1349  result = true;
1350  else
1351  result = false;
1352  return (bool) result;
1353  }
1354 
1355  /*
1356  * If we're asked about the built-in C/POSIX collations, we know that.
1357  */
1358  if (collation == C_COLLATION_OID ||
1359  collation == POSIX_COLLATION_OID)
1360  return true;
1361 
1362  /*
1363  * Otherwise, we have to consult pg_collation, but we cache that.
1364  */
1365  return (lookup_collation_cache(collation, true))->ctype_is_c;
1366 }

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

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

1456 {
1457  /* default locale must always be deterministic */
1458  if (locale == NULL)
1459  return true;
1460  else
1461  return locale->deterministic;
1462 }

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

1480 {
1481  collation_cache_entry *cache_entry;
1482 
1483  /* Callers must pass a valid OID */
1485 
1486  if (collid == DEFAULT_COLLATION_OID)
1487  {
1488  if (default_locale.provider == COLLPROVIDER_ICU)
1489  return &default_locale;
1490  else
1491  return (pg_locale_t) 0;
1492  }
1493 
1494  cache_entry = lookup_collation_cache(collid, false);
1495 
1496  if (cache_entry->locale == 0)
1497  {
1498  /* We haven't computed this yet in this session, so do it */
1499  HeapTuple tp;
1500  Form_pg_collation collform;
1501  struct pg_locale_struct result;
1502  pg_locale_t resultp;
1503  Datum datum;
1504  bool isnull;
1505 
1507  if (!HeapTupleIsValid(tp))
1508  elog(ERROR, "cache lookup failed for collation %u", collid);
1509  collform = (Form_pg_collation) GETSTRUCT(tp);
1510 
1511  /* We'll fill in the result struct locally before allocating memory */
1512  memset(&result, 0, sizeof(result));
1513  result.provider = collform->collprovider;
1514  result.deterministic = collform->collisdeterministic;
1515 
1516  if (collform->collprovider == COLLPROVIDER_LIBC)
1517  {
1518 #ifdef HAVE_LOCALE_T
1519  const char *collcollate;
1520  const char *collctype pg_attribute_unused();
1521  locale_t loc;
1522 
1523  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1524  collcollate = TextDatumGetCString(datum);
1525  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1526  collctype = TextDatumGetCString(datum);
1527 
1528  if (strcmp(collcollate, collctype) == 0)
1529  {
1530  /* Normal case where they're the same */
1531  errno = 0;
1532 #ifndef WIN32
1533  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1534  NULL);
1535 #else
1536  loc = _create_locale(LC_ALL, collcollate);
1537 #endif
1538  if (!loc)
1539  report_newlocale_failure(collcollate);
1540  }
1541  else
1542  {
1543 #ifndef WIN32
1544  /* We need two newlocale() steps */
1545  locale_t loc1;
1546 
1547  errno = 0;
1548  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1549  if (!loc1)
1550  report_newlocale_failure(collcollate);
1551  errno = 0;
1552  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1553  if (!loc)
1554  report_newlocale_failure(collctype);
1555 #else
1556 
1557  /*
1558  * XXX The _create_locale() API doesn't appear to support
1559  * this. Could perhaps be worked around by changing
1560  * pg_locale_t to contain two separate fields.
1561  */
1562  ereport(ERROR,
1563  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1564  errmsg("collations with different collate and ctype values are not supported on this platform")));
1565 #endif
1566  }
1567 
1568  result.info.lt = loc;
1569 #else /* not HAVE_LOCALE_T */
1570  /* platform that doesn't support locale_t */
1571  ereport(ERROR,
1572  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1573  errmsg("collation provider LIBC is not supported on this platform")));
1574 #endif /* not HAVE_LOCALE_T */
1575  }
1576  else if (collform->collprovider == COLLPROVIDER_ICU)
1577  {
1578  const char *iculocstr;
1579  const char *icurules;
1580 
1581  datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colliculocale);
1582  iculocstr = TextDatumGetCString(datum);
1583 
1584  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1585  if (!isnull)
1586  icurules = TextDatumGetCString(datum);
1587  else
1588  icurules = NULL;
1589 
1590  make_icu_collator(iculocstr, icurules, &result);
1591  }
1592 
1593  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1594  &isnull);
1595  if (!isnull)
1596  {
1597  char *actual_versionstr;
1598  char *collversionstr;
1599 
1600  collversionstr = TextDatumGetCString(datum);
1601 
1602  datum = SysCacheGetAttrNotNull(COLLOID, tp, collform->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate);
1603 
1604  actual_versionstr = get_collation_actual_version(collform->collprovider,
1605  TextDatumGetCString(datum));
1606  if (!actual_versionstr)
1607  {
1608  /*
1609  * This could happen when specifying a version in CREATE
1610  * COLLATION but the provider does not support versioning, or
1611  * manually creating a mess in the catalogs.
1612  */
1613  ereport(ERROR,
1614  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1615  NameStr(collform->collname))));
1616  }
1617 
1618  if (strcmp(actual_versionstr, collversionstr) != 0)
1619  ereport(WARNING,
1620  (errmsg("collation \"%s\" has version mismatch",
1621  NameStr(collform->collname)),
1622  errdetail("The collation in the database was created using version %s, "
1623  "but the operating system provides version %s.",
1624  collversionstr, actual_versionstr),
1625  errhint("Rebuild all objects affected by this collation and run "
1626  "ALTER COLLATION %s REFRESH VERSION, "
1627  "or build PostgreSQL with the right library version.",
1628  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1629  NameStr(collform->collname)))));
1630  }
1631 
1632  ReleaseSysCache(tp);
1633 
1634  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1635  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1636  *resultp = result;
1637 
1638  cache_entry->locale = resultp;
1639  }
1640 
1641  return cache_entry->locale;
1642 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:730
#define pg_attribute_unused()
Definition: c.h:120
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:3324
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:1371
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1649
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:12014
Definition: pg_locale.c:123
pg_locale_t locale
Definition: pg_locale.c:128
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1110
@ 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(), make_icu_collator(), MemoryContextAlloc(), NameStr, ObjectIdGetDatum(), OidIsValid, pg_attribute_unused, pg_locale_struct::provider, quote_qualified_identifier(), ReleaseSysCache(), 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 172 of file pg_locale.c.

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

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

2008 {
2009  int result;
2010 
2011  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2012  result = pg_strcoll_libc(arg1, arg2, locale);
2013 #ifdef USE_ICU
2014  else if (locale->provider == COLLPROVIDER_ICU)
2015  result = pg_strncoll_icu(arg1, -1, arg2, -1, locale);
2016 #endif
2017  else
2018  /* shouldn't happen */
2019  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2020 
2021  return result;
2022 }
static int pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale)
Definition: pg_locale.c:1818

References elog(), ERROR, locale, and pg_strcoll_libc().

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

2044 {
2045  int result;
2046 
2047  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2048  result = pg_strncoll_libc(arg1, len1, arg2, len2, locale);
2049 #ifdef USE_ICU
2050  else if (locale->provider == COLLPROVIDER_ICU)
2051  result = pg_strncoll_icu(arg1, len1, arg2, len2, locale);
2052 #endif
2053  else
2054  /* shouldn't happen */
2055  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2056 
2057  return result;
2058 }
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:1854

References elog(), ERROR, locale, and pg_strncoll_libc().

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

2330 {
2331  size_t result = 0; /* keep compiler quiet */
2332 
2333  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2334  result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale);
2335 #ifdef USE_ICU
2336  else if (locale->provider == COLLPROVIDER_ICU)
2337  result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale);
2338 #endif
2339  else
2340  /* shouldn't happen */
2341  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2342 
2343  return result;
2344 }
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:2082

References generate_unaccent_rules::dest, elog(), ERROR, locale, and pg_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,
size_t  srclen,
pg_locale_t  locale 
)

Definition at line 2415 of file pg_locale.c.

2417 {
2418  size_t result = 0; /* keep compiler quiet */
2419 
2420  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2421  elog(ERROR, "collprovider '%c' does not support pg_strnxfrm_prefix()",
2422  locale->provider);
2423 #ifdef USE_ICU
2424  else if (locale->provider == COLLPROVIDER_ICU)
2425  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2426 #endif
2427  else
2428  /* shouldn't happen */
2429  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2430 
2431  return result;
2432 }

References generate_unaccent_rules::dest, elog(), ERROR, and locale.

◆ pg_strxfrm()

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

Definition at line 2292 of file pg_locale.c.

2293 {
2294  size_t result = 0; /* keep compiler quiet */
2295 
2296  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2297  result = pg_strxfrm_libc(dest, src, destsize, locale);
2298 #ifdef USE_ICU
2299  else if (locale->provider == COLLPROVIDER_ICU)
2300  result = pg_strnxfrm_icu(dest, src, -1, destsize, locale);
2301 #endif
2302  else
2303  /* shouldn't happen */
2304  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2305 
2306  return result;
2307 }
static size_t pg_strxfrm_libc(char *dest, const char *src, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2062

References generate_unaccent_rules::dest, elog(), ERROR, locale, and pg_strxfrm_libc().

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_enabled()

bool pg_strxfrm_enabled ( pg_locale_t  locale)

Definition at line 2260 of file pg_locale.c.

2261 {
2262  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2263 #ifdef TRUST_STRXFRM
2264  return true;
2265 #else
2266  return false;
2267 #endif
2268  else if (locale->provider == COLLPROVIDER_ICU)
2269  return true;
2270  else
2271  /* shouldn't happen */
2272  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2273 
2274  return false; /* keep compiler quiet */
2275 }

References elog(), ERROR, and locale.

Referenced by varstr_sortsupport().

◆ pg_strxfrm_prefix()

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

Definition at line 2378 of file pg_locale.c.

2380 {
2381  size_t result = 0; /* keep compiler quiet */
2382 
2383  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2384  elog(ERROR, "collprovider '%c' does not support pg_strxfrm_prefix()",
2385  locale->provider);
2386 #ifdef USE_ICU
2387  else if (locale->provider == COLLPROVIDER_ICU)
2388  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2389 #endif
2390  else
2391  /* shouldn't happen */
2392  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2393 
2394  return result;
2395 }

References generate_unaccent_rules::dest, elog(), ERROR, and locale.

Referenced by varstr_abbrev_convert().

◆ pg_strxfrm_prefix_enabled()

bool pg_strxfrm_prefix_enabled ( pg_locale_t  locale)

Definition at line 2351 of file pg_locale.c.

2352 {
2353  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2354  return false;
2355  else if (locale->provider == COLLPROVIDER_ICU)
2356  return true;
2357  else
2358  /* shouldn't happen */
2359  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2360 
2361  return false; /* keep compiler quiet */
2362 }

References elog(), ERROR, and locale.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 484 of file pg_locale.c.

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

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

2937 {
2938  size_t result;
2939 
2940  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2941 
2942  if (tolen == 0)
2943  return 0;
2944 
2945 #ifdef WIN32
2946 
2947  /*
2948  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
2949  * for some reason mbstowcs and wcstombs won't do this for us, so we use
2950  * MultiByteToWideChar().
2951  */
2952  if (GetDatabaseEncoding() == PG_UTF8)
2953  {
2954  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
2955  NULL, NULL);
2956  /* A zero return is failure */
2957  if (result <= 0)
2958  result = -1;
2959  else
2960  {
2961  Assert(result <= tolen);
2962  /* Microsoft counts the zero terminator in the result */
2963  result--;
2964  }
2965  }
2966  else
2967 #endif /* WIN32 */
2968  if (locale == (pg_locale_t) 0)
2969  {
2970  /* Use wcstombs directly for the default locale */
2971  result = wcstombs(to, from, tolen);
2972  }
2973  else
2974  {
2975 #ifdef HAVE_LOCALE_T
2976 #ifdef HAVE_WCSTOMBS_L
2977  /* Use wcstombs_l for nondefault locales */
2978  result = wcstombs_l(to, from, tolen, locale->info.lt);
2979 #else /* !HAVE_WCSTOMBS_L */
2980  /* We have to temporarily set the locale as current ... ugh */
2981  locale_t save_locale = uselocale(locale->info.lt);
2982 
2983  result = wcstombs(to, from, tolen);
2984 
2985  uselocale(save_locale);
2986 #endif /* HAVE_WCSTOMBS_L */
2987 #else /* !HAVE_LOCALE_T */
2988  /* Can't have locale != 0 without HAVE_LOCALE_T */
2989  elog(ERROR, "wcstombs_l is not available");
2990  result = 0; /* keep compiler quiet */
2991 #endif /* HAVE_LOCALE_T */
2992  }
2993 
2994  return result;
2995 }
#define wcstombs_l
Definition: win32_port.h:458

References Assert(), elog(), ERROR, GetDatabaseEncoding(), locale, locale_t, 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 1319 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 99 of file pg_locale.c.

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

◆ locale_messages

PGDLLIMPORT char* locale_messages
extern

Definition at line 94 of file pg_locale.c.

◆ locale_monetary

PGDLLIMPORT char* locale_monetary
extern

Definition at line 95 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

PGDLLIMPORT char* locale_numeric
extern

Definition at line 96 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

PGDLLIMPORT char* locale_time
extern

Definition at line 97 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

PGDLLIMPORT char* localized_abbrev_days[]
extern

Definition at line 108 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 110 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 109 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 111 of file pg_locale.c.

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