PostgreSQL Source Code  git master
pg_locale.c File Reference
#include "postgres.h"
#include <time.h>
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_control.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/guc_hooks.h"
#include "utils/hsearch.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/syscache.h"
Include dependency graph for pg_locale.c:

Go to the source code of this file.

Data Structures

struct  collation_cache_entry
 

Macros

#define TEXTBUFLEN   1024
 
#define MAX_L10N_DATA   80
 

Functions

char * pg_perm_setlocale (int category, const char *locale)
 
bool check_locale (int category, const char *locale, char **canonname)
 
bool check_locale_monetary (char **newval, void **extra, GucSource source)
 
void assign_locale_monetary (const char *newval, void *extra)
 
bool check_locale_numeric (char **newval, void **extra, GucSource source)
 
void assign_locale_numeric (const char *newval, void *extra)
 
bool check_locale_time (char **newval, void **extra, GucSource source)
 
void assign_locale_time (const char *newval, void *extra)
 
bool check_locale_messages (char **newval, void **extra, GucSource source)
 
void assign_locale_messages (const char *newval, void *extra)
 
static void free_struct_lconv (struct lconv *s)
 
static bool struct_lconv_is_valid (struct lconv *s)
 
static void db_encoding_convert (int encoding, char **str)
 
struct lconv * PGLC_localeconv (void)
 
static void cache_single_string (char **dst, const char *src, int encoding)
 
void cache_locale_time (void)
 
void check_strxfrm_bug (void)
 
static collation_cache_entrylookup_collation_cache (Oid collation, bool set_flags)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
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)
 
static int pg_strcoll_libc (const char *arg1, const char *arg2, pg_locale_t locale)
 
static int pg_strncoll_libc (const char *arg1, size_t len1, const char *arg2, size_t len2, pg_locale_t locale)
 
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)
 
static size_t pg_strxfrm_libc (char *dest, const char *src, size_t destsize, pg_locale_t locale)
 
static size_t pg_strnxfrm_libc (char *dest, const char *src, size_t srclen, size_t destsize, 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 check_icu_locale (const char *icu_locale)
 
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

char * locale_messages
 
char * locale_monetary
 
char * locale_numeric
 
char * locale_time
 
char * localized_abbrev_days [7+1]
 
char * localized_full_days [7+1]
 
char * localized_abbrev_months [12+1]
 
char * localized_full_months [12+1]
 
bool database_ctype_is_c = false
 
static bool CurrentLocaleConvValid = false
 
static bool CurrentLCTimeValid = false
 
static HTABcollation_cache = NULL
 
struct pg_locale_struct default_locale
 

Macro Definition Documentation

◆ MAX_L10N_DATA

#define MAX_L10N_DATA   80

Definition at line 89 of file pg_locale.c.

◆ TEXTBUFLEN

#define TEXTBUFLEN   1024

Definition at line 87 of file pg_locale.c.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 382 of file pg_locale.c.

383 {
384  /*
385  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
386  * We ignore failure, as per comment above.
387  */
388 #ifdef LC_MESSAGES
389  (void) pg_perm_setlocale(LC_MESSAGES, newval);
390 #endif
391 }
#define newval
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:167

References newval, and pg_perm_setlocale().

◆ assign_locale_monetary()

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

Definition at line 319 of file pg_locale.c.

320 {
321  CurrentLocaleConvValid = false;
322 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:114

References CurrentLocaleConvValid.

◆ assign_locale_numeric()

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

Definition at line 331 of file pg_locale.c.

332 {
333  CurrentLocaleConvValid = false;
334 }

References CurrentLocaleConvValid.

◆ assign_locale_time()

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

Definition at line 343 of file pg_locale.c.

344 {
345  CurrentLCTimeValid = false;
346 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:115

References CurrentLCTimeValid.

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 761 of file pg_locale.c.

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

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

Referenced by DCH_from_char(), and DCH_to_char().

◆ cache_single_string()

static void cache_single_string ( char **  dst,
const char *  src,
int  encoding 
)
static

Definition at line 738 of file pg_locale.c.

739 {
740  char *ptr;
741  char *olddst;
742 
743  /* Convert the string to the database encoding, or validate it's OK */
744  ptr = pg_any_to_server(src, strlen(src), encoding);
745 
746  /* Store the string in long-lived storage, replacing any previous value */
747  olddst = *dst;
749  if (olddst)
750  pfree(olddst);
751 
752  /* Might as well clean up any palloc'd conversion result, too */
753  if (ptr != src)
754  pfree(ptr);
755 }
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:677
MemoryContext TopMemoryContext
Definition: mcxt.c:141
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1611

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

Referenced by cache_locale_time().

◆ char2wchar()

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

Definition at line 2877 of file pg_locale.c.

2879 {
2880  size_t result;
2881 
2882  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2883 
2884  if (tolen == 0)
2885  return 0;
2886 
2887 #ifdef WIN32
2888  /* See WIN32 "Unicode" comment above */
2889  if (GetDatabaseEncoding() == PG_UTF8)
2890  {
2891  /* Win32 API does not work for zero-length input */
2892  if (fromlen == 0)
2893  result = 0;
2894  else
2895  {
2896  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
2897  /* A zero return is failure */
2898  if (result == 0)
2899  result = -1;
2900  }
2901 
2902  if (result != -1)
2903  {
2904  Assert(result < tolen);
2905  /* Append trailing null wchar (MultiByteToWideChar() does not) */
2906  to[result] = 0;
2907  }
2908  }
2909  else
2910 #endif /* WIN32 */
2911  {
2912  /* mbstowcs requires ending '\0' */
2913  char *str = pnstrdup(from, fromlen);
2914 
2915  if (locale == (pg_locale_t) 0)
2916  {
2917  /* Use mbstowcs directly for the default locale */
2918  result = mbstowcs(to, str, tolen);
2919  }
2920  else
2921  {
2922 #ifdef HAVE_LOCALE_T
2923 #ifdef HAVE_MBSTOWCS_L
2924  /* Use mbstowcs_l for nondefault locales */
2925  result = mbstowcs_l(to, str, tolen, locale->info.lt);
2926 #else /* !HAVE_MBSTOWCS_L */
2927  /* We have to temporarily set the locale as current ... ugh */
2928  locale_t save_locale = uselocale(locale->info.lt);
2929 
2930  result = mbstowcs(to, str, tolen);
2931 
2932  uselocale(save_locale);
2933 #endif /* HAVE_MBSTOWCS_L */
2934 #else /* !HAVE_LOCALE_T */
2935  /* Can't have locale != 0 without HAVE_LOCALE_T */
2936  elog(ERROR, "mbstowcs_l is not available");
2937  result = 0; /* keep compiler quiet */
2938 #endif /* HAVE_LOCALE_T */
2939  }
2940 
2941  pfree(str);
2942  }
2943 
2944  if (result == -1)
2945  {
2946  /*
2947  * Invalid multibyte character encountered. We try to give a useful
2948  * error message by letting pg_verifymbstr check the string. But it's
2949  * possible that the string is OK to us, and not OK to mbstowcs ---
2950  * this suggests that the LC_CTYPE locale is different from the
2951  * database encoding. Give a generic error message if pg_verifymbstr
2952  * can't find anything wrong.
2953  */
2954  pg_verifymbstr(from, fromlen, false); /* might not return */
2955  /* but if it does ... */
2956  ereport(ERROR,
2957  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
2958  errmsg("invalid multibyte character for locale"),
2959  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
2960  }
2961 
2962  return result;
2963 }
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:1635
#define locale_t
Definition: win32_port.h:426
#define mbstowcs_l
Definition: win32_port.h:453

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

void check_icu_locale ( const char *  icu_locale)

Definition at line 2770 of file pg_locale.c.

2771 {
2772 #ifdef USE_ICU
2773  UCollator *collator;
2774  UErrorCode status;
2775 
2776  status = U_ZERO_ERROR;
2777  collator = ucol_open(icu_locale, &status);
2778  if (U_FAILURE(status))
2779  ereport(ERROR,
2780  (errmsg("could not open collator for locale \"%s\": %s",
2781  icu_locale, u_errorName(status))));
2782 
2783  if (U_ICU_VERSION_MAJOR_NUM < 54)
2784  icu_set_collation_attributes(collator, icu_locale);
2785  ucol_close(collator);
2786 #else
2787  ereport(ERROR,
2788  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2789  errmsg("ICU is not supported in this build")));
2790 #endif
2791 }
static char * icu_locale
Definition: initdb.c:151
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224

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

Referenced by createdb().

◆ check_locale()

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

Definition at line 270 of file pg_locale.c.

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

◆ check_locale_messages()

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

Definition at line 359 of file pg_locale.c.

360 {
361  if (**newval == '\0')
362  {
363  if (source == PGC_S_DEFAULT)
364  return true;
365  else
366  return false;
367  }
368 
369  /*
370  * LC_MESSAGES category does not exist everywhere, but accept it anyway
371  *
372  * On Windows, we can't even check the value, so accept blindly
373  */
374 #if defined(LC_MESSAGES) && !defined(WIN32)
375  return check_locale(LC_MESSAGES, *newval, NULL);
376 #else
377  return true;
378 #endif
379 }
@ PGC_S_DEFAULT
Definition: guc.h:109
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:270
static rewind_source * source
Definition: pg_rewind.c:87

References check_locale(), newval, PGC_S_DEFAULT, and source.

◆ check_locale_monetary()

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

Definition at line 313 of file pg_locale.c.

314 {
315  return check_locale(LC_MONETARY, *newval, NULL);
316 }

References check_locale(), and newval.

◆ check_locale_numeric()

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

Definition at line 325 of file pg_locale.c.

326 {
327  return check_locale(LC_NUMERIC, *newval, NULL);
328 }

References check_locale(), and newval.

◆ check_locale_time()

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

Definition at line 337 of file pg_locale.c.

338 {
339  return check_locale(LC_TIME, *newval, NULL);
340 }

References check_locale(), and newval.

◆ check_strxfrm_bug()

void check_strxfrm_bug ( void  )

Definition at line 1173 of file pg_locale.c.

1174 {
1175  char buf[32];
1176  const int canary = 0x7F;
1177  bool ok = true;
1178 
1179  /*
1180  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1181  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1182  * below that range.
1183  *
1184  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1185  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1186  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1187  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1188  */
1189  buf[7] = canary;
1190  (void) strxfrm(buf, "ab", 7);
1191  if (buf[7] != canary)
1192  ok = false;
1193 
1194  /*
1195  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1196  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1197  * affected systems ignore the length limit and modify a number of bytes
1198  * one less than the return value. The problem inputs for this bug do not
1199  * overlap those for the Solaris bug, hence a distinct test.
1200  *
1201  * Affected systems include smartos-20110926T021612Z. Affected locales
1202  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1203  */
1204  buf[1] = canary;
1205  (void) strxfrm(buf, "a", 1);
1206  if (buf[1] != canary)
1207  ok = false;
1208 
1209  if (!ok)
1210  ereport(ERROR,
1211  (errcode(ERRCODE_SYSTEM_ERROR),
1212  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1213  setlocale(LC_COLLATE, NULL)),
1214  errhint("Apply system library package updates.")));
1215 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156

References buf, ereport, errcode(), errhint(), errmsg_internal(), ERROR, and setlocale.

Referenced by CheckMyDatabase(), and main().

◆ db_encoding_convert()

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

Definition at line 449 of file pg_locale.c.

450 {
451  char *pstr;
452  char *mstr;
453 
454  /* convert the string to the database encoding */
455  pstr = pg_any_to_server(*str, strlen(*str), encoding);
456  if (pstr == *str)
457  return; /* no conversion happened */
458 
459  /* need it malloc'd not palloc'd */
460  mstr = strdup(pstr);
461  if (mstr == NULL)
462  ereport(ERROR,
463  (errcode(ERRCODE_OUT_OF_MEMORY),
464  errmsg("out of memory")));
465 
466  /* replace old string */
467  free(*str);
468  *str = mstr;
469 
470  pfree(pstr);
471 }
#define free(a)
Definition: header.h:65

References encoding, ereport, errcode(), errmsg(), ERROR, free, pfree(), pg_any_to_server(), and generate_unaccent_rules::str.

Referenced by PGLC_localeconv().

◆ free_struct_lconv()

static void free_struct_lconv ( struct lconv *  s)
static

Definition at line 399 of file pg_locale.c.

400 {
401  free(s->decimal_point);
402  free(s->thousands_sep);
403  free(s->grouping);
404  free(s->int_curr_symbol);
405  free(s->currency_symbol);
406  free(s->mon_decimal_point);
407  free(s->mon_thousands_sep);
408  free(s->mon_grouping);
409  free(s->positive_sign);
410  free(s->negative_sign);
411 }

References free.

Referenced by PGLC_localeconv().

◆ get_collation_actual_version()

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

Definition at line 1717 of file pg_locale.c.

1718 {
1719  char *collversion = NULL;
1720 
1721 #ifdef USE_ICU
1722  if (collprovider == COLLPROVIDER_ICU)
1723  {
1724  UCollator *collator;
1725  UErrorCode status;
1726  UVersionInfo versioninfo;
1727  char buf[U_MAX_VERSION_STRING_LENGTH];
1728 
1729  status = U_ZERO_ERROR;
1730  collator = ucol_open(collcollate, &status);
1731  if (U_FAILURE(status))
1732  ereport(ERROR,
1733  (errmsg("could not open collator for locale \"%s\": %s",
1734  collcollate, u_errorName(status))));
1735  ucol_getVersion(collator, versioninfo);
1736  ucol_close(collator);
1737 
1738  u_versionToString(versioninfo, buf);
1739  collversion = pstrdup(buf);
1740  }
1741  else
1742 #endif
1743  if (collprovider == COLLPROVIDER_LIBC &&
1744  pg_strcasecmp("C", collcollate) != 0 &&
1745  pg_strncasecmp("C.", collcollate, 2) != 0 &&
1746  pg_strcasecmp("POSIX", collcollate) != 0)
1747  {
1748 #if defined(__GLIBC__)
1749  /* Use the glibc version because we don't have anything better. */
1750  collversion = pstrdup(gnu_get_libc_version());
1751 #elif defined(LC_VERSION_MASK)
1752  locale_t loc;
1753 
1754  /* Look up FreeBSD collation version. */
1755  loc = newlocale(LC_COLLATE, collcollate, NULL);
1756  if (loc)
1757  {
1758  collversion =
1759  pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
1760  freelocale(loc);
1761  }
1762  else
1763  ereport(ERROR,
1764  (errmsg("could not load locale \"%s\"", collcollate)));
1765 #elif defined(WIN32)
1766  /*
1767  * If we are targeting Windows Vista and above, we can ask for a name
1768  * given a collation name (earlier versions required a location code
1769  * that we don't have).
1770  */
1771  NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
1772  WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
1773 
1774  MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
1775  LOCALE_NAME_MAX_LENGTH);
1776  if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1777  {
1778  /*
1779  * GetNLSVersionEx() wants a language tag such as "en-US", not a
1780  * locale name like "English_United States.1252". Until those
1781  * values can be prevented from entering the system, or 100%
1782  * reliably converted to the more useful tag format, tolerate the
1783  * resulting error and report that we have no version data.
1784  */
1785  if (GetLastError() == ERROR_INVALID_PARAMETER)
1786  return NULL;
1787 
1788  ereport(ERROR,
1789  (errmsg("could not get collation version for locale \"%s\": error code %lu",
1790  collcollate,
1791  GetLastError())));
1792  }
1793  collversion = psprintf("%ld.%ld,%ld.%ld",
1794  (version.dwNLSVersion >> 8) & 0xFFFF,
1795  version.dwNLSVersion & 0xFF,
1796  (version.dwDefinedVersion >> 8) & 0xFFFF,
1797  version.dwDefinedVersion & 0xFF);
1798 #endif
1799  }
1800 
1801  return collversion;
1802 }
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(), pstrdup(), and status().

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

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1322 of file pg_locale.c.

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

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

1376 {
1377  /*
1378  * If we're asked about "collation 0", return false, so that the code will
1379  * go into the non-C path and report that the collation is bogus.
1380  */
1381  if (!OidIsValid(collation))
1382  return false;
1383 
1384  /*
1385  * If we're asked about the default collation, we have to inquire of the C
1386  * library. Cache the result so we only have to compute it once.
1387  */
1388  if (collation == DEFAULT_COLLATION_OID)
1389  {
1390  static int result = -1;
1391  char *localeptr;
1392 
1393  if (default_locale.provider == COLLPROVIDER_ICU)
1394  return false;
1395 
1396  if (result >= 0)
1397  return (bool) result;
1398  localeptr = setlocale(LC_CTYPE, NULL);
1399  if (!localeptr)
1400  elog(ERROR, "invalid LC_CTYPE setting");
1401 
1402  if (strcmp(localeptr, "C") == 0)
1403  result = true;
1404  else if (strcmp(localeptr, "POSIX") == 0)
1405  result = true;
1406  else
1407  result = false;
1408  return (bool) result;
1409  }
1410 
1411  /*
1412  * If we're asked about the built-in C/POSIX collations, we know that.
1413  */
1414  if (collation == C_COLLATION_OID ||
1415  collation == POSIX_COLLATION_OID)
1416  return true;
1417 
1418  /*
1419  * Otherwise, we have to consult pg_collation, but we cache that.
1420  */
1421  return (lookup_collation_cache(collation, true))->ctype_is_c;
1422 }

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

◆ lookup_collation_cache()

static collation_cache_entry* lookup_collation_cache ( Oid  collation,
bool  set_flags 
)
static

Definition at line 1243 of file pg_locale.c.

1244 {
1245  collation_cache_entry *cache_entry;
1246  bool found;
1247 
1248  Assert(OidIsValid(collation));
1249  Assert(collation != DEFAULT_COLLATION_OID);
1250 
1251  if (collation_cache == NULL)
1252  {
1253  /* First time through, initialize the hash table */
1254  HASHCTL ctl;
1255 
1256  ctl.keysize = sizeof(Oid);
1257  ctl.entrysize = sizeof(collation_cache_entry);
1258  collation_cache = hash_create("Collation cache", 100, &ctl,
1259  HASH_ELEM | HASH_BLOBS);
1260  }
1261 
1262  cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
1263  if (!found)
1264  {
1265  /*
1266  * Make sure cache entry is marked invalid, in case we fail before
1267  * setting things.
1268  */
1269  cache_entry->flags_valid = false;
1270  cache_entry->locale = 0;
1271  }
1272 
1273  if (set_flags && !cache_entry->flags_valid)
1274  {
1275  /* Attempt to set the flags */
1276  HeapTuple tp;
1277  Form_pg_collation collform;
1278 
1279  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1280  if (!HeapTupleIsValid(tp))
1281  elog(ERROR, "cache lookup failed for collation %u", collation);
1282  collform = (Form_pg_collation) GETSTRUCT(tp);
1283 
1284  if (collform->collprovider == COLLPROVIDER_LIBC)
1285  {
1286  Datum datum;
1287  bool isnull;
1288  const char *collcollate;
1289  const char *collctype;
1290 
1291  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
1292  Assert(!isnull);
1293  collcollate = TextDatumGetCString(datum);
1294  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
1295  Assert(!isnull);
1296  collctype = TextDatumGetCString(datum);
1297 
1298  cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) ||
1299  (strcmp(collcollate, "POSIX") == 0));
1300  cache_entry->ctype_is_c = ((strcmp(collctype, "C") == 0) ||
1301  (strcmp(collctype, "POSIX") == 0));
1302  }
1303  else
1304  {
1305  cache_entry->collate_is_c = false;
1306  cache_entry->ctype_is_c = false;
1307  }
1308 
1309  cache_entry->flags_valid = true;
1310 
1311  ReleaseSysCache(tp);
1312  }
1313 
1314  return cache_entry;
1315 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
static HTAB * collation_cache
Definition: pg_locale.c:128
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
Definition: pg_locale.c:120
bool collate_is_c
Definition: pg_locale.c:122
pg_locale_t locale
Definition: pg_locale.c:125
bool flags_valid
Definition: pg_locale.c:124
bool ctype_is_c
Definition: pg_locale.c:123
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:865
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:817
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1078
@ COLLOID
Definition: syscache.h:50

References Assert(), collation_cache_entry::collate_is_c, collation_cache, COLLOID, collation_cache_entry::ctype_is_c, elog(), HASHCTL::entrysize, ERROR, collation_cache_entry::flags_valid, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, HASHCTL::keysize, collation_cache_entry::locale, ObjectIdGetDatum(), OidIsValid, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), and TextDatumGetCString.

Referenced by lc_collate_is_c(), and pg_newlocale_from_collation().

◆ make_icu_collator()

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

Definition at line 1427 of file pg_locale.c.

1430 {
1431 #ifdef USE_ICU
1432  UCollator *collator;
1433  UErrorCode status;
1434 
1435  status = U_ZERO_ERROR;
1436  collator = ucol_open(iculocstr, &status);
1437  if (U_FAILURE(status))
1438  ereport(ERROR,
1439  (errmsg("could not open collator for locale \"%s\": %s",
1440  iculocstr, u_errorName(status))));
1441 
1442  if (U_ICU_VERSION_MAJOR_NUM < 54)
1443  icu_set_collation_attributes(collator, iculocstr);
1444 
1445  /*
1446  * If rules are specified, we extract the rules of the standard collation,
1447  * add our own rules, and make a new collator with the combined rules.
1448  */
1449  if (icurules)
1450  {
1451  const UChar *default_rules;
1452  UChar *agg_rules;
1453  UChar *my_rules;
1454  int32_t length;
1455 
1456  default_rules = ucol_getRules(collator, &length);
1457  icu_to_uchar(&my_rules, icurules, strlen(icurules));
1458 
1459  agg_rules = palloc_array(UChar, u_strlen(default_rules) + u_strlen(my_rules) + 1);
1460  u_strcpy(agg_rules, default_rules);
1461  u_strcat(agg_rules, my_rules);
1462 
1463  ucol_close(collator);
1464 
1465  status = U_ZERO_ERROR;
1466  collator = ucol_openRules(agg_rules, u_strlen(agg_rules),
1467  UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
1468  if (U_FAILURE(status))
1469  ereport(ERROR,
1470  (errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s",
1471  iculocstr, icurules, u_errorName(status))));
1472  }
1473 
1474  /* We will leak this string if the caller errors later :-( */
1475  resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1476  resultp->info.icu.ucol = collator;
1477 #else /* not USE_ICU */
1478  /* could get here if a collation was created by a build with ICU */
1479  ereport(ERROR,
1480  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1481  errmsg("ICU is not supported in this build")));
1482 #endif /* not USE_ICU */
1483 }
#define palloc_array(type, count)
Definition: fe_memutils.h:64
union pg_locale_struct::@140 info

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

Referenced by CheckMyDatabase(), and pg_newlocale_from_collation().

◆ pg_locale_deterministic()

bool pg_locale_deterministic ( pg_locale_t  locale)

Definition at line 1519 of file pg_locale.c.

1520 {
1521  /* default locale must always be deterministic */
1522  if (locale == NULL)
1523  return true;
1524  else
1525  return locale->deterministic;
1526 }

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

1544 {
1545  collation_cache_entry *cache_entry;
1546 
1547  /* Callers must pass a valid OID */
1549 
1550  if (collid == DEFAULT_COLLATION_OID)
1551  {
1552  if (default_locale.provider == COLLPROVIDER_ICU)
1553  return &default_locale;
1554  else
1555  return (pg_locale_t) 0;
1556  }
1557 
1558  cache_entry = lookup_collation_cache(collid, false);
1559 
1560  if (cache_entry->locale == 0)
1561  {
1562  /* We haven't computed this yet in this session, so do it */
1563  HeapTuple tp;
1564  Form_pg_collation collform;
1565  struct pg_locale_struct result;
1566  pg_locale_t resultp;
1567  Datum datum;
1568  bool isnull;
1569 
1571  if (!HeapTupleIsValid(tp))
1572  elog(ERROR, "cache lookup failed for collation %u", collid);
1573  collform = (Form_pg_collation) GETSTRUCT(tp);
1574 
1575  /* We'll fill in the result struct locally before allocating memory */
1576  memset(&result, 0, sizeof(result));
1577  result.provider = collform->collprovider;
1578  result.deterministic = collform->collisdeterministic;
1579 
1580  if (collform->collprovider == COLLPROVIDER_LIBC)
1581  {
1582 #ifdef HAVE_LOCALE_T
1583  const char *collcollate;
1584  const char *collctype pg_attribute_unused();
1585  locale_t loc;
1586 
1587  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
1588  Assert(!isnull);
1589  collcollate = TextDatumGetCString(datum);
1590  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
1591  Assert(!isnull);
1592  collctype = TextDatumGetCString(datum);
1593 
1594  if (strcmp(collcollate, collctype) == 0)
1595  {
1596  /* Normal case where they're the same */
1597  errno = 0;
1598 #ifndef WIN32
1599  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1600  NULL);
1601 #else
1602  loc = _create_locale(LC_ALL, collcollate);
1603 #endif
1604  if (!loc)
1605  report_newlocale_failure(collcollate);
1606  }
1607  else
1608  {
1609 #ifndef WIN32
1610  /* We need two newlocale() steps */
1611  locale_t loc1;
1612 
1613  errno = 0;
1614  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1615  if (!loc1)
1616  report_newlocale_failure(collcollate);
1617  errno = 0;
1618  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1619  if (!loc)
1620  report_newlocale_failure(collctype);
1621 #else
1622 
1623  /*
1624  * XXX The _create_locale() API doesn't appear to support
1625  * this. Could perhaps be worked around by changing
1626  * pg_locale_t to contain two separate fields.
1627  */
1628  ereport(ERROR,
1629  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1630  errmsg("collations with different collate and ctype values are not supported on this platform")));
1631 #endif
1632  }
1633 
1634  result.info.lt = loc;
1635 #else /* not HAVE_LOCALE_T */
1636  /* platform that doesn't support locale_t */
1637  ereport(ERROR,
1638  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1639  errmsg("collation provider LIBC is not supported on this platform")));
1640 #endif /* not HAVE_LOCALE_T */
1641  }
1642  else if (collform->collprovider == COLLPROVIDER_ICU)
1643  {
1644  const char *iculocstr;
1645  const char *icurules;
1646 
1647  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colliculocale, &isnull);
1648  Assert(!isnull);
1649  iculocstr = TextDatumGetCString(datum);
1650 
1651  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1652  if (!isnull)
1653  icurules = TextDatumGetCString(datum);
1654  else
1655  icurules = NULL;
1656 
1657  make_icu_collator(iculocstr, icurules, &result);
1658  }
1659 
1660  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1661  &isnull);
1662  if (!isnull)
1663  {
1664  char *actual_versionstr;
1665  char *collversionstr;
1666 
1667  collversionstr = TextDatumGetCString(datum);
1668 
1669  datum = SysCacheGetAttr(COLLOID, tp, collform->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate, &isnull);
1670  Assert(!isnull);
1671 
1672  actual_versionstr = get_collation_actual_version(collform->collprovider,
1673  TextDatumGetCString(datum));
1674  if (!actual_versionstr)
1675  {
1676  /*
1677  * This could happen when specifying a version in CREATE
1678  * COLLATION but the provider does not support versioning, or
1679  * manually creating a mess in the catalogs.
1680  */
1681  ereport(ERROR,
1682  (errmsg("collation \"%s\" has no actual version, but a version was recorded",
1683  NameStr(collform->collname))));
1684  }
1685 
1686  if (strcmp(actual_versionstr, collversionstr) != 0)
1687  ereport(WARNING,
1688  (errmsg("collation \"%s\" has version mismatch",
1689  NameStr(collform->collname)),
1690  errdetail("The collation in the database was created using version %s, "
1691  "but the operating system provides version %s.",
1692  collversionstr, actual_versionstr),
1693  errhint("Rebuild all objects affected by this collation and run "
1694  "ALTER COLLATION %s REFRESH VERSION, "
1695  "or build PostgreSQL with the right library version.",
1696  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1697  NameStr(collform->collname)))));
1698  }
1699 
1700  ReleaseSysCache(tp);
1701 
1702  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1703  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1704  *resultp = result;
1705 
1706  cache_entry->locale = resultp;
1707  }
1708 
1709  return cache_entry->locale;
1710 }
#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
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3331
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1005
void make_icu_collator(const char *iculocstr, const char *icurules, struct pg_locale_struct *resultp)
Definition: pg_locale.c:1427
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1717
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11635

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(), 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 167 of file pg_locale.c.

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

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

2081 {
2082  int result;
2083 
2084  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2085  result = pg_strcoll_libc(arg1, arg2, locale);
2086 #ifdef USE_ICU
2087  else if (locale->provider == COLLPROVIDER_ICU)
2088  result = pg_strncoll_icu(arg1, -1, arg2, -1, locale);
2089 #endif
2090  else
2091  /* shouldn't happen */
2092  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2093 
2094  return result;
2095 }
static int pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale)
Definition: pg_locale.c:1892

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

Referenced by varstrfastcmp_locale().

◆ pg_strcoll_libc()

static int pg_strcoll_libc ( const char *  arg1,
const char *  arg2,
pg_locale_t  locale 
)
static

Definition at line 1892 of file pg_locale.c.

1893 {
1894  int result;
1895 
1896  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1897 #ifdef WIN32
1898  if (GetDatabaseEncoding() == PG_UTF8)
1899  {
1900  size_t len1 = strlen(arg1);
1901  size_t len2 = strlen(arg2);
1902  result = pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1903  }
1904  else
1905 #endif /* WIN32 */
1906  if (locale)
1907  {
1908 #ifdef HAVE_LOCALE_T
1909  result = strcoll_l(arg1, arg2, locale->info.lt);
1910 #else
1911  /* shouldn't happen */
1912  elog(ERROR, "unsupported collprovider: %c", locale->provider);
1913 #endif
1914  }
1915  else
1916  result = strcoll(arg1, arg2);
1917 
1918  return result;
1919 }
#define strcoll_l
Definition: win32_port.h:449

References Assert(), elog(), ERROR, GetDatabaseEncoding(), locale, PG_UTF8, and strcoll_l.

Referenced by pg_strcoll(), and pg_strncoll_libc().

◆ pg_strncoll()

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

Definition at line 2115 of file pg_locale.c.

2117 {
2118  int result;
2119 
2120  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2121  result = pg_strncoll_libc(arg1, len1, arg2, len2, locale);
2122 #ifdef USE_ICU
2123  else if (locale->provider == COLLPROVIDER_ICU)
2124  result = pg_strncoll_icu(arg1, len1, arg2, len2, locale);
2125 #endif
2126  else
2127  /* shouldn't happen */
2128  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2129 
2130  return result;
2131 }
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:1927

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

Referenced by varstr_cmp().

◆ pg_strncoll_libc()

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

Definition at line 1927 of file pg_locale.c.

1929 {
1930  char sbuf[TEXTBUFLEN];
1931  char *buf = sbuf;
1932  size_t bufsize1 = len1 + 1;
1933  size_t bufsize2 = len2 + 1;
1934  char *arg1n;
1935  char *arg2n;
1936  int result;
1937 
1938  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
1939 
1940 #ifdef WIN32
1941  /* check for this case before doing the work for nul-termination */
1942  if (GetDatabaseEncoding() == PG_UTF8)
1943  return pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale);
1944 #endif /* WIN32 */
1945 
1946  if (bufsize1 + bufsize2 > TEXTBUFLEN)
1947  buf = palloc(bufsize1 + bufsize2);
1948 
1949  arg1n = buf;
1950  arg2n = buf + bufsize1;
1951 
1952  /* nul-terminate arguments */
1953  memcpy(arg1n, arg1, len1);
1954  arg1n[len1] = '\0';
1955  memcpy(arg2n, arg2, len2);
1956  arg2n[len2] = '\0';
1957 
1958  result = pg_strcoll_libc(arg1n, arg2n, locale);
1959 
1960  if (buf != sbuf)
1961  pfree(buf);
1962 
1963  return result;
1964 }
void * palloc(Size size)
Definition: mcxt.c:1210
#define TEXTBUFLEN
Definition: pg_locale.c:87

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

Referenced by pg_strncoll().

◆ pg_strnxfrm()

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

Definition at line 2401 of file pg_locale.c.

2403 {
2404  size_t result = 0; /* keep compiler quiet */
2405 
2406  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2407  result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale);
2408 #ifdef USE_ICU
2409  else if (locale->provider == COLLPROVIDER_ICU)
2410  result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale);
2411 #endif
2412  else
2413  /* shouldn't happen */
2414  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2415 
2416  return result;
2417 }
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:2155

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

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

◆ pg_strnxfrm_libc()

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

Definition at line 2155 of file pg_locale.c.

2157 {
2158  char sbuf[TEXTBUFLEN];
2159  char *buf = sbuf;
2160  size_t bufsize = srclen + 1;
2161  size_t result;
2162 
2163  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2164 
2165  if (bufsize > TEXTBUFLEN)
2166  buf = palloc(bufsize);
2167 
2168  /* nul-terminate arguments */
2169  memcpy(buf, src, srclen);
2170  buf[srclen] = '\0';
2171 
2172  result = pg_strxfrm_libc(dest, buf, destsize, locale);
2173 
2174  if (buf != sbuf)
2175  pfree(buf);
2176 
2177  /* if dest is defined, it should be nul-terminated */
2178  Assert(result >= destsize || dest[result] == '\0');
2179 
2180  return result;
2181 }
#define bufsize
Definition: indent_globs.h:36
static size_t pg_strxfrm_libc(char *dest, const char *src, size_t destsize, pg_locale_t locale)
Definition: pg_locale.c:2135

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

Referenced by pg_strnxfrm().

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

2490 {
2491  size_t result = 0; /* keep compiler quiet */
2492 
2493  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2494  elog(ERROR, "collprovider '%c' does not support pg_strnxfrm_prefix()",
2495  locale->provider);
2496 #ifdef USE_ICU
2497  else if (locale->provider == COLLPROVIDER_ICU)
2498  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2499 #endif
2500  else
2501  /* shouldn't happen */
2502  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2503 
2504  return result;
2505 }

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

2366 {
2367  size_t result = 0; /* keep compiler quiet */
2368 
2369  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2370  result = pg_strxfrm_libc(dest, src, destsize, locale);
2371 #ifdef USE_ICU
2372  else if (locale->provider == COLLPROVIDER_ICU)
2373  result = pg_strnxfrm_icu(dest, src, -1, destsize, locale);
2374 #endif
2375  else
2376  /* shouldn't happen */
2377  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2378 
2379  return result;
2380 }

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

2334 {
2335  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2336 #ifdef TRUST_STRXFRM
2337  return true;
2338 #else
2339  return false;
2340 #endif
2341  else if (locale->provider == COLLPROVIDER_ICU)
2342  return true;
2343  else
2344  /* shouldn't happen */
2345  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2346 
2347  return false; /* keep compiler quiet */
2348 }

References elog(), ERROR, and locale.

Referenced by varstr_sortsupport().

◆ pg_strxfrm_libc()

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

Definition at line 2135 of file pg_locale.c.

2137 {
2138  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2139 
2140 #ifdef TRUST_STRXFRM
2141 #ifdef HAVE_LOCALE_T
2142  if (locale)
2143  return strxfrm_l(dest, src, destsize, locale->info.lt);
2144  else
2145 #endif
2146  return strxfrm(dest, src, destsize);
2147 #else
2148  /* shouldn't happen */
2149  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2150  return 0; /* keep compiler quiet */
2151 #endif
2152 }
#define strxfrm_l
Definition: win32_port.h:450

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

Referenced by pg_strnxfrm_libc(), and pg_strxfrm().

◆ pg_strxfrm_prefix()

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

Definition at line 2451 of file pg_locale.c.

2453 {
2454  size_t result = 0; /* keep compiler quiet */
2455 
2456  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2457  elog(ERROR, "collprovider '%c' does not support pg_strxfrm_prefix()",
2458  locale->provider);
2459 #ifdef USE_ICU
2460  else if (locale->provider == COLLPROVIDER_ICU)
2461  result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale);
2462 #endif
2463  else
2464  /* shouldn't happen */
2465  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2466 
2467  return result;
2468 }

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

2425 {
2426  if (!locale || locale->provider == COLLPROVIDER_LIBC)
2427  return false;
2428  else if (locale->provider == COLLPROVIDER_ICU)
2429  return true;
2430  else
2431  /* shouldn't happen */
2432  elog(ERROR, "unsupported collprovider: %c", locale->provider);
2433 
2434  return false; /* keep compiler quiet */
2435 }

References elog(), ERROR, and locale.

Referenced by varstr_abbrev_convert().

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 479 of file pg_locale.c.

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

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

◆ struct_lconv_is_valid()

static bool struct_lconv_is_valid ( struct lconv *  s)
static

Definition at line 418 of file pg_locale.c.

419 {
420  if (s->decimal_point == NULL)
421  return false;
422  if (s->thousands_sep == NULL)
423  return false;
424  if (s->grouping == NULL)
425  return false;
426  if (s->int_curr_symbol == NULL)
427  return false;
428  if (s->currency_symbol == NULL)
429  return false;
430  if (s->mon_decimal_point == NULL)
431  return false;
432  if (s->mon_thousands_sep == NULL)
433  return false;
434  if (s->mon_grouping == NULL)
435  return false;
436  if (s->positive_sign == NULL)
437  return false;
438  if (s->negative_sign == NULL)
439  return false;
440  return true;
441 }

Referenced by PGLC_localeconv().

◆ wchar2char()

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

Definition at line 2806 of file pg_locale.c.

2807 {
2808  size_t result;
2809 
2810  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2811 
2812  if (tolen == 0)
2813  return 0;
2814 
2815 #ifdef WIN32
2816 
2817  /*
2818  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
2819  * for some reason mbstowcs and wcstombs won't do this for us, so we use
2820  * MultiByteToWideChar().
2821  */
2822  if (GetDatabaseEncoding() == PG_UTF8)
2823  {
2824  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
2825  NULL, NULL);
2826  /* A zero return is failure */
2827  if (result <= 0)
2828  result = -1;
2829  else
2830  {
2831  Assert(result <= tolen);
2832  /* Microsoft counts the zero terminator in the result */
2833  result--;
2834  }
2835  }
2836  else
2837 #endif /* WIN32 */
2838  if (locale == (pg_locale_t) 0)
2839  {
2840  /* Use wcstombs directly for the default locale */
2841  result = wcstombs(to, from, tolen);
2842  }
2843  else
2844  {
2845 #ifdef HAVE_LOCALE_T
2846 #ifdef HAVE_WCSTOMBS_L
2847  /* Use wcstombs_l for nondefault locales */
2848  result = wcstombs_l(to, from, tolen, locale->info.lt);
2849 #else /* !HAVE_WCSTOMBS_L */
2850  /* We have to temporarily set the locale as current ... ugh */
2851  locale_t save_locale = uselocale(locale->info.lt);
2852 
2853  result = wcstombs(to, from, tolen);
2854 
2855  uselocale(save_locale);
2856 #endif /* HAVE_WCSTOMBS_L */
2857 #else /* !HAVE_LOCALE_T */
2858  /* Can't have locale != 0 without HAVE_LOCALE_T */
2859  elog(ERROR, "wcstombs_l is not available");
2860  result = 0; /* keep compiler quiet */
2861 #endif /* HAVE_LOCALE_T */
2862  }
2863 
2864  return result;
2865 }
#define wcstombs_l
Definition: win32_port.h:452

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

◆ collation_cache

HTAB* collation_cache = NULL
static

Definition at line 128 of file pg_locale.c.

Referenced by lookup_collation_cache().

◆ CurrentLCTimeValid

bool CurrentLCTimeValid = false
static

Definition at line 115 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

◆ CurrentLocaleConvValid

bool CurrentLocaleConvValid = false
static

Definition at line 114 of file pg_locale.c.

Referenced by assign_locale_monetary(), assign_locale_numeric(), and PGLC_localeconv().

◆ database_ctype_is_c

bool database_ctype_is_c = false

◆ default_locale

struct pg_locale_struct default_locale

◆ locale_messages

char* locale_messages

Definition at line 93 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 94 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 95 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 96 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[7+1]

Definition at line 105 of file pg_locale.c.

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

◆ localized_abbrev_months

char* localized_abbrev_months[12+1]

Definition at line 107 of file pg_locale.c.

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

◆ localized_full_days

char* localized_full_days[7+1]

Definition at line 106 of file pg_locale.c.

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

◆ localized_full_months

char* localized_full_months[12+1]

Definition at line 108 of file pg_locale.c.

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