PostgreSQL Source Code  git master
pg_locale.h File Reference
#include "utils/guc.h"
Include dependency graph for pg_locale.h:
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
 

Typedefs

typedef struct pg_locale_structpg_locale_t
 

Functions

bool check_locale_messages (char **newval, void **extra, GucSource source)
 
void assign_locale_messages (const char *newval, void *extra)
 
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 (int category, const char *locale, char **canonname)
 
char * pg_perm_setlocale (int category, const char *locale)
 
void check_strxfrm_bug (void)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
struct lconv * PGLC_localeconv (void)
 
void cache_locale_time (void)
 
pg_locale_t pg_newlocale_from_collation (Oid collid)
 
char * get_collation_version_for_oid (Oid collid)
 
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 []
 
char * localized_full_days []
 
char * localized_abbrev_months []
 
char * localized_full_months []
 

Typedef Documentation

◆ pg_locale_t

typedef struct pg_locale_struct* pg_locale_t

Definition at line 102 of file pg_locale.h.

Function Documentation

◆ assign_locale_messages()

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

Definition at line 388 of file pg_locale.c.

References pg_perm_setlocale().

389 {
390  /*
391  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
392  * We ignore failure, as per comment above.
393  */
394 #ifdef LC_MESSAGES
395  (void) pg_perm_setlocale(LC_MESSAGES, newval);
396 #endif
397 }
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:162
#define newval

◆ assign_locale_monetary()

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

Definition at line 325 of file pg_locale.c.

References CurrentLocaleConvValid.

326 {
327  CurrentLocaleConvValid = false;
328 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:105

◆ assign_locale_numeric()

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

Definition at line 337 of file pg_locale.c.

References CurrentLocaleConvValid.

338 {
339  CurrentLocaleConvValid = false;
340 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:105

◆ assign_locale_time()

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

Definition at line 349 of file pg_locale.c.

References CurrentLCTimeValid.

350 {
351  CurrentLCTimeValid = false;
352 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:106

◆ cache_locale_time()

void cache_locale_time ( void  )

Definition at line 777 of file pg_locale.c.

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_mbstrlen(), PG_SQL_ASCII, pg_strcasecmp(), PG_UTF8, pstrdup(), setlocale, tm, and wchar2char().

Referenced by DCH_from_char(), and DCH_to_char().

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

◆ char2wchar()

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

Definition at line 2090 of file pg_locale.c.

References Assert, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, locale_t, mbstowcs_l, pfree(), PG_UTF8, pg_verifymbstr(), pnstrdup(), pg_locale_struct::provider, and generate_unaccent_rules::str.

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

2092 {
2093  size_t result;
2094 
2095  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2096 
2097  if (tolen == 0)
2098  return 0;
2099 
2100 #ifdef WIN32
2101  /* See WIN32 "Unicode" comment above */
2102  if (GetDatabaseEncoding() == PG_UTF8)
2103  {
2104  /* Win32 API does not work for zero-length input */
2105  if (fromlen == 0)
2106  result = 0;
2107  else
2108  {
2109  result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
2110  /* A zero return is failure */
2111  if (result == 0)
2112  result = -1;
2113  }
2114 
2115  if (result != -1)
2116  {
2117  Assert(result < tolen);
2118  /* Append trailing null wchar (MultiByteToWideChar() does not) */
2119  to[result] = 0;
2120  }
2121  }
2122  else
2123 #endif /* WIN32 */
2124  {
2125  /* mbstowcs requires ending '\0' */
2126  char *str = pnstrdup(from, fromlen);
2127 
2128  if (locale == (pg_locale_t) 0)
2129  {
2130  /* Use mbstowcs directly for the default locale */
2131  result = mbstowcs(to, str, tolen);
2132  }
2133  else
2134  {
2135 #ifdef HAVE_LOCALE_T
2136 #ifdef HAVE_MBSTOWCS_L
2137  /* Use mbstowcs_l for nondefault locales */
2138  result = mbstowcs_l(to, str, tolen, locale->info.lt);
2139 #else /* !HAVE_MBSTOWCS_L */
2140  /* We have to temporarily set the locale as current ... ugh */
2141  locale_t save_locale = uselocale(locale->info.lt);
2142 
2143  result = mbstowcs(to, str, tolen);
2144 
2145  uselocale(save_locale);
2146 #endif /* HAVE_MBSTOWCS_L */
2147 #else /* !HAVE_LOCALE_T */
2148  /* Can't have locale != 0 without HAVE_LOCALE_T */
2149  elog(ERROR, "mbstowcs_l is not available");
2150  result = 0; /* keep compiler quiet */
2151 #endif /* HAVE_LOCALE_T */
2152  }
2153 
2154  pfree(str);
2155  }
2156 
2157  if (result == -1)
2158  {
2159  /*
2160  * Invalid multibyte character encountered. We try to give a useful
2161  * error message by letting pg_verifymbstr check the string. But it's
2162  * possible that the string is OK to us, and not OK to mbstowcs ---
2163  * this suggests that the LC_CTYPE locale is different from the
2164  * database encoding. Give a generic error message if pg_verifymbstr
2165  * can't find anything wrong.
2166  */
2167  pg_verifymbstr(from, fromlen, false); /* might not return */
2168  /* but if it does ... */
2169  ereport(ERROR,
2170  (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
2171  errmsg("invalid multibyte character for locale"),
2172  errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
2173  }
2174 
2175  return result;
2176 }
int errhint(const char *fmt,...)
Definition: elog.c:1149
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
int errcode(int sqlerrcode)
Definition: elog.c:691
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
#define locale_t
Definition: win32_port.h:391
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1446
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:800
#define mbstowcs_l
Definition: win32_port.h:418
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
union pg_locale_struct::@142 info

◆ check_locale()

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

Definition at line 276 of file pg_locale.c.

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

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

277 {
278  char *save;
279  char *res;
280 
281  if (canonname)
282  *canonname = NULL; /* in case of failure */
283 
284  save = setlocale(category, NULL);
285  if (!save)
286  return false; /* won't happen, we hope */
287 
288  /* save may be pointing at a modifiable scratch variable, see above. */
289  save = pstrdup(save);
290 
291  /* set the locale with setlocale, to see if it accepts it. */
292  res = setlocale(category, locale);
293 
294  /* save canonical name if requested. */
295  if (res && canonname)
296  *canonname = pstrdup(res);
297 
298  /* restore old value. */
299  if (!setlocale(category, save))
300  elog(WARNING, "failed to restore old locale \"%s\"", save);
301  pfree(save);
302 
303  return (res != NULL);
304 }
#define setlocale(a, b)
Definition: win32_port.h:436
char * pstrdup(const char *in)
Definition: mcxt.c:1187
void pfree(void *pointer)
Definition: mcxt.c:1057
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:228
static char * locale
Definition: initdb.c:126

◆ check_locale_messages()

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

Definition at line 365 of file pg_locale.c.

References check_locale(), and PGC_S_DEFAULT.

366 {
367  if (**newval == '\0')
368  {
369  if (source == PGC_S_DEFAULT)
370  return true;
371  else
372  return false;
373  }
374 
375  /*
376  * LC_MESSAGES category does not exist everywhere, but accept it anyway
377  *
378  * On Windows, we can't even check the value, so accept blindly
379  */
380 #if defined(LC_MESSAGES) && !defined(WIN32)
381  return check_locale(LC_MESSAGES, *newval, NULL);
382 #else
383  return true;
384 #endif
385 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:276
static rewind_source * source
Definition: pg_rewind.c:79
#define newval

◆ check_locale_monetary()

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

Definition at line 319 of file pg_locale.c.

References check_locale().

320 {
321  return check_locale(LC_MONETARY, *newval, NULL);
322 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:276
#define newval

◆ check_locale_numeric()

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

Definition at line 331 of file pg_locale.c.

References check_locale().

332 {
333  return check_locale(LC_NUMERIC, *newval, NULL);
334 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:276
#define newval

◆ check_locale_time()

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

Definition at line 343 of file pg_locale.c.

References check_locale().

344 {
345  return check_locale(LC_TIME, *newval, NULL);
346 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:276
#define newval

◆ check_strxfrm_bug()

void check_strxfrm_bug ( void  )

Definition at line 1217 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

1218 {
1219  char buf[32];
1220  const int canary = 0x7F;
1221  bool ok = true;
1222 
1223  /*
1224  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1225  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1226  * below that range.
1227  *
1228  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1229  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1230  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1231  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1232  */
1233  buf[7] = canary;
1234  (void) strxfrm(buf, "ab", 7);
1235  if (buf[7] != canary)
1236  ok = false;
1237 
1238  /*
1239  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1240  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1241  * affected systems ignore the length limit and modify a number of bytes
1242  * one less than the return value. The problem inputs for this bug do not
1243  * overlap those for the Solaris bug, hence a distinct test.
1244  *
1245  * Affected systems include smartos-20110926T021612Z. Affected locales
1246  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1247  */
1248  buf[1] = canary;
1249  (void) strxfrm(buf, "a", 1);
1250  if (buf[1] != canary)
1251  ok = false;
1252 
1253  if (!ok)
1254  ereport(ERROR,
1255  (errcode(ERRCODE_SYSTEM_ERROR),
1256  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1257  setlocale(LC_COLLATE, NULL)),
1258  errhint("Apply system library package updates.")));
1259 }
int errhint(const char *fmt,...)
Definition: elog.c:1149
#define setlocale(a, b)
Definition: win32_port.h:436
int errcode(int sqlerrcode)
Definition: elog.c:691
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg_internal(const char *fmt,...)
Definition: elog.c:989

◆ get_collation_version_for_oid()

char* get_collation_version_for_oid ( Oid  collid)

Definition at line 1758 of file pg_locale.c.

References asc_tolower(), COLLOID, DATABASEOID, elog, ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), get_encoding_name_for_icu(), GetDatabaseEncoding(), GETSTRUCT, HeapTupleIsValid, MyDatabaseId, name, NameStr, ObjectIdGetDatum, palloc(), pg_attribute_unused(), pg_encoding_to_char(), ReleaseSysCache(), SearchSysCache1(), status(), generate_unaccent_rules::str, and value.

Referenced by do_collation_version_check(), do_collation_version_update(), pg_collation_actual_version(), and recordMultipleDependencies().

1759 {
1760  HeapTuple tp;
1761  char *version;
1762 
1763  if (oid == DEFAULT_COLLATION_OID)
1764  {
1765  Form_pg_database dbform;
1766 
1768  if (!HeapTupleIsValid(tp))
1769  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
1770  dbform = (Form_pg_database) GETSTRUCT(tp);
1771  version = get_collation_actual_version(COLLPROVIDER_LIBC,
1772  NameStr(dbform->datcollate));
1773  }
1774  else
1775  {
1776  Form_pg_collation collform;
1777 
1779  if (!HeapTupleIsValid(tp))
1780  elog(ERROR, "cache lookup failed for collation %u", oid);
1781  collform = (Form_pg_collation) GETSTRUCT(tp);
1782  version = get_collation_actual_version(collform->collprovider,
1783  NameStr(collform->collcollate));
1784  }
1785 
1786  ReleaseSysCache(tp);
1787 
1788  return version;
1789 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1639
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
Oid MyDatabaseId
Definition: globals.c:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677

◆ lc_collate_is_c()

bool lc_collate_is_c ( Oid  collation)

Definition at line 1352 of file pg_locale.c.

References elog, ERROR, lookup_collation_cache(), OidIsValid, 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().

1353 {
1354  /*
1355  * If we're asked about "collation 0", return false, so that the code will
1356  * go into the non-C path and report that the collation is bogus.
1357  */
1358  if (!OidIsValid(collation))
1359  return false;
1360 
1361  /*
1362  * If we're asked about the default collation, we have to inquire of the C
1363  * library. Cache the result so we only have to compute it once.
1364  */
1365  if (collation == DEFAULT_COLLATION_OID)
1366  {
1367  static int result = -1;
1368  char *localeptr;
1369 
1370  if (result >= 0)
1371  return (bool) result;
1372  localeptr = setlocale(LC_COLLATE, NULL);
1373  if (!localeptr)
1374  elog(ERROR, "invalid LC_COLLATE setting");
1375 
1376  if (strcmp(localeptr, "C") == 0)
1377  result = true;
1378  else if (strcmp(localeptr, "POSIX") == 0)
1379  result = true;
1380  else
1381  result = false;
1382  return (bool) result;
1383  }
1384 
1385  /*
1386  * If we're asked about the built-in C/POSIX collations, we know that.
1387  */
1388  if (collation == C_COLLATION_OID ||
1389  collation == POSIX_COLLATION_OID)
1390  return true;
1391 
1392  /*
1393  * Otherwise, we have to consult pg_collation, but we cache that.
1394  */
1395  return (lookup_collation_cache(collation, true))->collate_is_c;
1396 }
#define setlocale(a, b)
Definition: win32_port.h:436
#define OidIsValid(objectId)
Definition: c.h:706
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:228
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1287

◆ lc_ctype_is_c()

bool lc_ctype_is_c ( Oid  collation)

Definition at line 1402 of file pg_locale.c.

References elog, ereport, errcode(), errdetail(), errmsg(), ERROR, lookup_collation_cache(), OidIsValid, and setlocale.

Referenced by DefineCollation(), Generic_Text_IC_like(), GenericMatchText(), like_fixed_prefix(), lowerstr_with_len(), pg_set_regex_collation(), str_initcap(), str_tolower(), str_toupper(), t_isalpha(), t_isdigit(), t_isprint(), t_isspace(), and TParserInit().

1403 {
1404  /*
1405  * If we're asked about "collation 0", return false, so that the code will
1406  * go into the non-C path and report that the collation is bogus.
1407  */
1408  if (!OidIsValid(collation))
1409  return false;
1410 
1411  /*
1412  * If we're asked about the default collation, we have to inquire of the C
1413  * library. Cache the result so we only have to compute it once.
1414  */
1415  if (collation == DEFAULT_COLLATION_OID)
1416  {
1417  static int result = -1;
1418  char *localeptr;
1419 
1420  if (result >= 0)
1421  return (bool) result;
1422  localeptr = setlocale(LC_CTYPE, NULL);
1423  if (!localeptr)
1424  elog(ERROR, "invalid LC_CTYPE setting");
1425 
1426  if (strcmp(localeptr, "C") == 0)
1427  result = true;
1428  else if (strcmp(localeptr, "POSIX") == 0)
1429  result = true;
1430  else
1431  result = false;
1432  return (bool) result;
1433  }
1434 
1435  /*
1436  * If we're asked about the built-in C/POSIX collations, we know that.
1437  */
1438  if (collation == C_COLLATION_OID ||
1439  collation == POSIX_COLLATION_OID)
1440  return true;
1441 
1442  /*
1443  * Otherwise, we have to consult pg_collation, but we cache that.
1444  */
1445  return (lookup_collation_cache(collation, true))->ctype_is_c;
1446 }
#define setlocale(a, b)
Definition: win32_port.h:436
#define OidIsValid(objectId)
Definition: c.h:706
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:228
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1287

◆ pg_newlocale_from_collation()

pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1499 of file pg_locale.c.

References Assert, COLLOID, pg_locale_struct::deterministic, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, pg_locale_struct::info, collation_cache_entry::locale, locale_t, lookup_collation_cache(), MemoryContextAlloc(), MemoryContextStrdup(), NameStr, ObjectIdGetDatum, OidIsValid, pg_attribute_unused(), pg_locale_struct::provider, ReleaseSysCache(), SearchSysCache1(), status(), and TopMemoryContext.

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

1500 {
1501  collation_cache_entry *cache_entry;
1502 
1503  /* Callers must pass a valid OID */
1504  Assert(OidIsValid(collid));
1505 
1506  /* Return 0 for "default" collation, just in case caller forgets */
1507  if (collid == DEFAULT_COLLATION_OID)
1508  return (pg_locale_t) 0;
1509 
1510  cache_entry = lookup_collation_cache(collid, false);
1511 
1512  if (cache_entry->locale == 0)
1513  {
1514  /* We haven't computed this yet in this session, so do it */
1515  HeapTuple tp;
1516  Form_pg_collation collform;
1517  const char *collcollate pg_attribute_unused();
1518  const char *collctype pg_attribute_unused();
1519  struct pg_locale_struct result;
1520  pg_locale_t resultp;
1521 
1522  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1523  if (!HeapTupleIsValid(tp))
1524  elog(ERROR, "cache lookup failed for collation %u", collid);
1525  collform = (Form_pg_collation) GETSTRUCT(tp);
1526 
1527  collcollate = NameStr(collform->collcollate);
1528  collctype = NameStr(collform->collctype);
1529 
1530  /* We'll fill in the result struct locally before allocating memory */
1531  memset(&result, 0, sizeof(result));
1532  result.provider = collform->collprovider;
1533  result.deterministic = collform->collisdeterministic;
1534 
1535  if (collform->collprovider == COLLPROVIDER_LIBC)
1536  {
1537 #ifdef HAVE_LOCALE_T
1538  locale_t loc;
1539 
1540  if (strcmp(collcollate, collctype) == 0)
1541  {
1542  /* Normal case where they're the same */
1543  errno = 0;
1544 #ifndef WIN32
1545  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1546  NULL);
1547 #else
1548  loc = _create_locale(LC_ALL, collcollate);
1549 #endif
1550  if (!loc)
1551  report_newlocale_failure(collcollate);
1552  }
1553  else
1554  {
1555 #ifndef WIN32
1556  /* We need two newlocale() steps */
1557  locale_t loc1;
1558 
1559  errno = 0;
1560  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1561  if (!loc1)
1562  report_newlocale_failure(collcollate);
1563  errno = 0;
1564  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1565  if (!loc)
1566  report_newlocale_failure(collctype);
1567 #else
1568 
1569  /*
1570  * XXX The _create_locale() API doesn't appear to support
1571  * this. Could perhaps be worked around by changing
1572  * pg_locale_t to contain two separate fields.
1573  */
1574  ereport(ERROR,
1575  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1576  errmsg("collations with different collate and ctype values are not supported on this platform")));
1577 #endif
1578  }
1579 
1580  result.info.lt = loc;
1581 #else /* not HAVE_LOCALE_T */
1582  /* platform that doesn't support locale_t */
1583  ereport(ERROR,
1584  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1585  errmsg("collation provider LIBC is not supported on this platform")));
1586 #endif /* not HAVE_LOCALE_T */
1587  }
1588  else if (collform->collprovider == COLLPROVIDER_ICU)
1589  {
1590 #ifdef USE_ICU
1591  UCollator *collator;
1592  UErrorCode status;
1593 
1594  if (strcmp(collcollate, collctype) != 0)
1595  ereport(ERROR,
1596  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1597  errmsg("collations with different collate and ctype values are not supported by ICU")));
1598 
1599  status = U_ZERO_ERROR;
1600  collator = ucol_open(collcollate, &status);
1601  if (U_FAILURE(status))
1602  ereport(ERROR,
1603  (errmsg("could not open collator for locale \"%s\": %s",
1604  collcollate, u_errorName(status))));
1605 
1606  if (U_ICU_VERSION_MAJOR_NUM < 54)
1607  icu_set_collation_attributes(collator, collcollate);
1608 
1609  /* We will leak this string if we get an error below :-( */
1610  result.info.icu.locale = MemoryContextStrdup(TopMemoryContext,
1611  collcollate);
1612  result.info.icu.ucol = collator;
1613 #else /* not USE_ICU */
1614  /* could get here if a collation was created by a build with ICU */
1615  ereport(ERROR,
1616  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1617  errmsg("ICU is not supported in this build"), \
1618  errhint("You need to rebuild PostgreSQL using --with-icu.")));
1619 #endif /* not USE_ICU */
1620  }
1621 
1622  ReleaseSysCache(tp);
1623 
1624  /* We'll keep the pg_locale_t structures in TopMemoryContext */
1625  resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1626  *resultp = result;
1627 
1628  cache_entry->locale = resultp;
1629  }
1630 
1631  return cache_entry->locale;
1632 }
int errhint(const char *fmt,...)
Definition: elog.c:1149
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int errcode(int sqlerrcode)
Definition: elog.c:691
#define OidIsValid(objectId)
Definition: c.h:706
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define locale_t
Definition: win32_port.h:391
MemoryContext TopMemoryContext
Definition: mcxt.c:44
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
pg_locale_t locale
Definition: pg_locale.c:130
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
pg_attribute_unused()
Definition: isn.c:63
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1287
Definition: pg_locale.c:124
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ pg_perm_setlocale()

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

Definition at line 162 of file pg_locale.c.

References DEBUG3, elog, FATAL, GetDatabaseEncoding(), lc_collate_envbuf, lc_ctype_envbuf, LC_ENV_BUFSIZE, lc_monetary_envbuf, lc_numeric_envbuf, lc_time_envbuf, putenv, setlocale, SetMessageEncoding(), snprintf, and strlcpy().

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

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

◆ PGLC_localeconv()

struct lconv* PGLC_localeconv ( void  )

Definition at line 495 of file pg_locale.c.

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

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

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

◆ wchar2char()

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

Definition at line 2019 of file pg_locale.c.

References Assert, elog, ERROR, GetDatabaseEncoding(), pg_locale_struct::info, locale_t, PG_UTF8, pg_locale_struct::provider, and wcstombs_l.

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

2020 {
2021  size_t result;
2022 
2023  Assert(!locale || locale->provider == COLLPROVIDER_LIBC);
2024 
2025  if (tolen == 0)
2026  return 0;
2027 
2028 #ifdef WIN32
2029 
2030  /*
2031  * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and
2032  * for some reason mbstowcs and wcstombs won't do this for us, so we use
2033  * MultiByteToWideChar().
2034  */
2035  if (GetDatabaseEncoding() == PG_UTF8)
2036  {
2037  result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
2038  NULL, NULL);
2039  /* A zero return is failure */
2040  if (result <= 0)
2041  result = -1;
2042  else
2043  {
2044  Assert(result <= tolen);
2045  /* Microsoft counts the zero terminator in the result */
2046  result--;
2047  }
2048  }
2049  else
2050 #endif /* WIN32 */
2051  if (locale == (pg_locale_t) 0)
2052  {
2053  /* Use wcstombs directly for the default locale */
2054  result = wcstombs(to, from, tolen);
2055  }
2056  else
2057  {
2058 #ifdef HAVE_LOCALE_T
2059 #ifdef HAVE_WCSTOMBS_L
2060  /* Use wcstombs_l for nondefault locales */
2061  result = wcstombs_l(to, from, tolen, locale->info.lt);
2062 #else /* !HAVE_WCSTOMBS_L */
2063  /* We have to temporarily set the locale as current ... ugh */
2064  locale_t save_locale = uselocale(locale->info.lt);
2065 
2066  result = wcstombs(to, from, tolen);
2067 
2068  uselocale(save_locale);
2069 #endif /* HAVE_WCSTOMBS_L */
2070 #else /* !HAVE_LOCALE_T */
2071  /* Can't have locale != 0 without HAVE_LOCALE_T */
2072  elog(ERROR, "wcstombs_l is not available");
2073  result = 0; /* keep compiler quiet */
2074 #endif /* HAVE_LOCALE_T */
2075  }
2076 
2077  return result;
2078 }
#define wcstombs_l
Definition: win32_port.h:417
#define ERROR
Definition: elog.h:43
#define locale_t
Definition: win32_port.h:391
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
#define Assert(condition)
Definition: c.h:800
#define elog(elevel,...)
Definition: elog.h:228
union pg_locale_struct::@142 info

Variable Documentation

◆ locale_messages

char* locale_messages

Definition at line 87 of file pg_locale.c.

◆ locale_monetary

char* locale_monetary

Definition at line 88 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_numeric

char* locale_numeric

Definition at line 89 of file pg_locale.c.

Referenced by PGLC_localeconv().

◆ locale_time

char* locale_time

Definition at line 90 of file pg_locale.c.

Referenced by cache_locale_time().

◆ localized_abbrev_days

char* localized_abbrev_days[]

Definition at line 99 of file pg_locale.c.

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

◆ localized_abbrev_months

char* localized_abbrev_months[]

Definition at line 101 of file pg_locale.c.

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

◆ localized_full_days

char* localized_full_days[]

Definition at line 100 of file pg_locale.c.

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

◆ localized_full_months

char* localized_full_months[]

Definition at line 102 of file pg_locale.c.

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