PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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_actual_version (char collprovider, const char *collcollate)
 

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

Definition at line 88 of file pg_locale.h.

Function Documentation

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

Definition at line 376 of file pg_locale.c.

References pg_perm_setlocale().

377 {
378  /*
379  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
380  * We ignore failure, as per comment above.
381  */
382 #ifdef LC_MESSAGES
383  (void) pg_perm_setlocale(LC_MESSAGES, newval);
384 #endif
385 }
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:151
#define newval
void assign_locale_monetary ( const char *  newval,
void *  extra 
)

Definition at line 313 of file pg_locale.c.

References CurrentLocaleConvValid.

314 {
315  CurrentLocaleConvValid = false;
316 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:100
void assign_locale_numeric ( 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:100
void assign_locale_time ( const char *  newval,
void *  extra 
)

Definition at line 337 of file pg_locale.c.

References CurrentLCTimeValid.

338 {
339  CurrentLCTimeValid = false;
340 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:101
void cache_locale_time ( void  )

Definition at line 786 of file pg_locale.c.

References cache_single_time(), CurrentLCTimeValid, DEBUG3, elog, i, locale_time, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, NULL, pfree(), pstrdup(), timenow(), and WARNING.

Referenced by DCH_to_char().

787 {
788  char *save_lc_time;
789  time_t timenow;
790  struct tm *timeinfo;
791  int i;
792 
793 #ifdef WIN32
794  char *save_lc_ctype;
795 #endif
796 
797  /* did we do this already? */
798  if (CurrentLCTimeValid)
799  return;
800 
801  elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
802 
803  /* save user's value of time locale */
804  save_lc_time = setlocale(LC_TIME, NULL);
805  if (save_lc_time)
806  save_lc_time = pstrdup(save_lc_time);
807 
808 #ifdef WIN32
809 
810  /*
811  * On WIN32, there is no way to get locale-specific time values in a
812  * specified locale, like we do for monetary/numeric. We can only get
813  * CP_ACP (see strftime_win32) or UTF16. Therefore, we get UTF16 and
814  * convert it to the database locale. However, wcsftime() internally uses
815  * LC_CTYPE, so we set it here. See the WIN32 comment near the top of
816  * PGLC_localeconv().
817  */
818 
819  /* save user's value of ctype locale */
820  save_lc_ctype = setlocale(LC_CTYPE, NULL);
821  if (save_lc_ctype)
822  save_lc_ctype = pstrdup(save_lc_ctype);
823 
824  /* use lc_time to set the ctype */
825  setlocale(LC_CTYPE, locale_time);
826 #endif
827 
828  setlocale(LC_TIME, locale_time);
829 
830  timenow = time(NULL);
831  timeinfo = localtime(&timenow);
832 
833  /* localized days */
834  for (i = 0; i < 7; i++)
835  {
836  timeinfo->tm_wday = i;
837  cache_single_time(&localized_abbrev_days[i], "%a", timeinfo);
838  cache_single_time(&localized_full_days[i], "%A", timeinfo);
839  }
840 
841  /* localized months */
842  for (i = 0; i < 12; i++)
843  {
844  timeinfo->tm_mon = i;
845  timeinfo->tm_mday = 1; /* make sure we don't have invalid date */
846  cache_single_time(&localized_abbrev_months[i], "%b", timeinfo);
847  cache_single_time(&localized_full_months[i], "%B", timeinfo);
848  }
849 
850  /* try to restore internal settings */
851  if (save_lc_time)
852  {
853  if (!setlocale(LC_TIME, save_lc_time))
854  elog(WARNING, "failed to restore old locale");
855  pfree(save_lc_time);
856  }
857 
858 #ifdef WIN32
859  /* try to restore internal ctype settings */
860  if (save_lc_ctype)
861  {
862  if (!setlocale(LC_CTYPE, save_lc_ctype))
863  elog(WARNING, "failed to restore old locale");
864  pfree(save_lc_ctype);
865  }
866 #endif
867 
868  CurrentLCTimeValid = true;
869 }
#define DEBUG3
Definition: elog.h:23
char * pstrdup(const char *in)
Definition: mcxt.c:1077
Datum timenow(PG_FUNCTION_ARGS)
Definition: nabstime.c:997
char * localized_abbrev_months[12]
Definition: pg_locale.c:96
static struct pg_tm tm
Definition: localtime.c:111
void pfree(void *pointer)
Definition: mcxt.c:950
#define WARNING
Definition: elog.h:40
char * localized_full_days[7]
Definition: pg_locale.c:95
#define NULL
Definition: c.h:229
int i
#define elog
Definition: elog.h:219
char * localized_full_months[12]
Definition: pg_locale.c:97
char * localized_abbrev_days[7]
Definition: pg_locale.c:94
static void cache_single_time(char **dst, const char *format, const struct tm *tm)
Definition: pg_locale.c:759
char * locale_time
Definition: pg_locale.c:91
static bool CurrentLCTimeValid
Definition: pg_locale.c:101
bool check_locale ( int  category,
const char *  locale,
char **  canonname 
)

Definition at line 264 of file pg_locale.c.

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

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

265 {
266  char *save;
267  char *res;
268 
269  if (canonname)
270  *canonname = NULL; /* in case of failure */
271 
272  save = setlocale(category, NULL);
273  if (!save)
274  return false; /* won't happen, we hope */
275 
276  /* save may be pointing at a modifiable scratch variable, see above. */
277  save = pstrdup(save);
278 
279  /* set the locale with setlocale, to see if it accepts it. */
280  res = setlocale(category, locale);
281 
282  /* save canonical name if requested. */
283  if (res && canonname)
284  *canonname = pstrdup(res);
285 
286  /* restore old value. */
287  if (!setlocale(category, save))
288  elog(WARNING, "failed to restore old locale \"%s\"", save);
289  pfree(save);
290 
291  return (res != NULL);
292 }
char * pstrdup(const char *in)
Definition: mcxt.c:1077
void pfree(void *pointer)
Definition: mcxt.c:950
#define WARNING
Definition: elog.h:40
#define NULL
Definition: c.h:229
static char * locale
Definition: initdb.c:123
#define elog
Definition: elog.h:219
bool check_locale_messages ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 353 of file pg_locale.c.

References check_locale(), NULL, and PGC_S_DEFAULT.

354 {
355  if (**newval == '\0')
356  {
357  if (source == PGC_S_DEFAULT)
358  return true;
359  else
360  return false;
361  }
362 
363  /*
364  * LC_MESSAGES category does not exist everywhere, but accept it anyway
365  *
366  * On Windows, we can't even check the value, so accept blindly
367  */
368 #if defined(LC_MESSAGES) && !defined(WIN32)
369  return check_locale(LC_MESSAGES, *newval, NULL);
370 #else
371  return true;
372 #endif
373 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define NULL
Definition: c.h:229
#define newval
bool check_locale_monetary ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 307 of file pg_locale.c.

References check_locale(), and NULL.

308 {
309  return check_locale(LC_MONETARY, *newval, NULL);
310 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define NULL
Definition: c.h:229
#define newval
bool check_locale_numeric ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 319 of file pg_locale.c.

References check_locale(), and NULL.

320 {
321  return check_locale(LC_NUMERIC, *newval, NULL);
322 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define NULL
Definition: c.h:229
#define newval
bool check_locale_time ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 331 of file pg_locale.c.

References check_locale(), and NULL.

332 {
333  return check_locale(LC_TIME, *newval, NULL);
334 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:264
#define NULL
Definition: c.h:229
#define newval
void check_strxfrm_bug ( void  )

Definition at line 993 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

994 {
995  char buf[32];
996  const int canary = 0x7F;
997  bool ok = true;
998 
999  /*
1000  * Given a two-byte ASCII string and length limit 7, 8 or 9, Solaris 10
1001  * 05/08 returns 18 and modifies 10 bytes. It respects limits above or
1002  * below that range.
1003  *
1004  * The bug is present in Solaris 8 as well; it is absent in Solaris 10
1005  * 01/13 and Solaris 11.2. Affected locales include is_IS.ISO8859-1,
1006  * en_US.UTF-8, en_US.ISO8859-1, and ru_RU.KOI8-R. Unaffected locales
1007  * include de_DE.UTF-8, de_DE.ISO8859-1, zh_TW.UTF-8, and C.
1008  */
1009  buf[7] = canary;
1010  (void) strxfrm(buf, "ab", 7);
1011  if (buf[7] != canary)
1012  ok = false;
1013 
1014  /*
1015  * illumos bug #1594 was present in the source tree from 2010-10-11 to
1016  * 2012-02-01. Given an ASCII string of any length and length limit 1,
1017  * affected systems ignore the length limit and modify a number of bytes
1018  * one less than the return value. The problem inputs for this bug do not
1019  * overlap those for the Solaris bug, hence a distinct test.
1020  *
1021  * Affected systems include smartos-20110926T021612Z. Affected locales
1022  * include en_US.ISO8859-1 and en_US.UTF-8. Unaffected locales include C.
1023  */
1024  buf[1] = canary;
1025  (void) strxfrm(buf, "a", 1);
1026  if (buf[1] != canary)
1027  ok = false;
1028 
1029  if (!ok)
1030  ereport(ERROR,
1031  (errcode(ERRCODE_SYSTEM_ERROR),
1032  errmsg_internal("strxfrm(), in locale \"%s\", writes past the specified array length",
1033  setlocale(LC_COLLATE, NULL)),
1034  errhint("Apply system library package updates.")));
1035 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:66
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
#define NULL
Definition: c.h:229
char* get_collation_actual_version ( char  collprovider,
const char *  collcollate 
)

Definition at line 1427 of file pg_locale.c.

References buf, COLLPROVIDER_ICU, ereport, errmsg(), ERROR, NULL, pstrdup(), and status().

Referenced by AlterCollation(), DefineCollation(), pg_collation_actual_version(), pg_import_system_collations(), and pg_newlocale_from_collation().

1428 {
1429  char *collversion;
1430 
1431 #ifdef USE_ICU
1432  if (collprovider == COLLPROVIDER_ICU)
1433  {
1434  UCollator *collator;
1435  UErrorCode status;
1436  UVersionInfo versioninfo;
1437  char buf[U_MAX_VERSION_STRING_LENGTH];
1438 
1439  status = U_ZERO_ERROR;
1440  collator = ucol_open(collcollate, &status);
1441  if (U_FAILURE(status))
1442  ereport(ERROR,
1443  (errmsg("could not open collator for locale \"%s\": %s",
1444  collcollate, u_errorName(status))));
1445  ucol_getVersion(collator, versioninfo);
1446  ucol_close(collator);
1447 
1448  u_versionToString(versioninfo, buf);
1449  collversion = pstrdup(buf);
1450  }
1451  else
1452 #endif
1453  collversion = NULL;
1454 
1455  return collversion;
1456 }
#define COLLPROVIDER_ICU
Definition: pg_collation.h:85
char * pstrdup(const char *in)
Definition: mcxt.c:1077
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:66
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
bool lc_collate_is_c ( Oid  collation)

Definition at line 1128 of file pg_locale.c.

References C_COLLATION_OID, DEFAULT_COLLATION_OID, elog, ERROR, lookup_collation_cache(), NULL, OidIsValid, POSIX_COLLATION_OID, and result.

Referenced by convert_string_datum(), make_greater_string(), match_special_index_operator(), spg_text_inner_consistent(), varstr_cmp(), and varstr_sortsupport().

1129 {
1130  /*
1131  * If we're asked about "collation 0", return false, so that the code will
1132  * go into the non-C path and report that the collation is bogus.
1133  */
1134  if (!OidIsValid(collation))
1135  return false;
1136 
1137  /*
1138  * If we're asked about the default collation, we have to inquire of the C
1139  * library. Cache the result so we only have to compute it once.
1140  */
1141  if (collation == DEFAULT_COLLATION_OID)
1142  {
1143  static int result = -1;
1144  char *localeptr;
1145 
1146  if (result >= 0)
1147  return (bool) result;
1148  localeptr = setlocale(LC_COLLATE, NULL);
1149  if (!localeptr)
1150  elog(ERROR, "invalid LC_COLLATE setting");
1151 
1152  if (strcmp(localeptr, "C") == 0)
1153  result = true;
1154  else if (strcmp(localeptr, "POSIX") == 0)
1155  result = true;
1156  else
1157  result = false;
1158  return (bool) result;
1159  }
1160 
1161  /*
1162  * If we're asked about the built-in C/POSIX collations, we know that.
1163  */
1164  if (collation == C_COLLATION_OID ||
1165  collation == POSIX_COLLATION_OID)
1166  return true;
1167 
1168  /*
1169  * Otherwise, we have to consult pg_collation, but we cache that.
1170  */
1171  return (lookup_collation_cache(collation, true))->collate_is_c;
1172 }
return result
Definition: formatting.c:1632
#define OidIsValid(objectId)
Definition: c.h:538
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define NULL
Definition: c.h:229
#define C_COLLATION_OID
Definition: pg_collation.h:78
#define POSIX_COLLATION_OID
Definition: pg_collation.h:81
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
bool lc_ctype_is_c ( Oid  collation)

Definition at line 1178 of file pg_locale.c.

References C_COLLATION_OID, DEFAULT_COLLATION_OID, elog, ERROR, lookup_collation_cache(), NULL, OidIsValid, POSIX_COLLATION_OID, and result.

Referenced by Generic_Text_IC_like(), like_fixed_prefix(), lowerstr_with_len(), pg_set_regex_collation(), str_initcap(), str_tolower(), str_toupper(), and TParserInit().

1179 {
1180  /*
1181  * If we're asked about "collation 0", return false, so that the code will
1182  * go into the non-C path and report that the collation is bogus.
1183  */
1184  if (!OidIsValid(collation))
1185  return false;
1186 
1187  /*
1188  * If we're asked about the default collation, we have to inquire of the C
1189  * library. Cache the result so we only have to compute it once.
1190  */
1191  if (collation == DEFAULT_COLLATION_OID)
1192  {
1193  static int result = -1;
1194  char *localeptr;
1195 
1196  if (result >= 0)
1197  return (bool) result;
1198  localeptr = setlocale(LC_CTYPE, NULL);
1199  if (!localeptr)
1200  elog(ERROR, "invalid LC_CTYPE setting");
1201 
1202  if (strcmp(localeptr, "C") == 0)
1203  result = true;
1204  else if (strcmp(localeptr, "POSIX") == 0)
1205  result = true;
1206  else
1207  result = false;
1208  return (bool) result;
1209  }
1210 
1211  /*
1212  * If we're asked about the built-in C/POSIX collations, we know that.
1213  */
1214  if (collation == C_COLLATION_OID ||
1215  collation == POSIX_COLLATION_OID)
1216  return true;
1217 
1218  /*
1219  * Otherwise, we have to consult pg_collation, but we cache that.
1220  */
1221  return (lookup_collation_cache(collation, true))->ctype_is_c;
1222 }
return result
Definition: formatting.c:1632
#define OidIsValid(objectId)
Definition: c.h:538
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define NULL
Definition: c.h:229
#define C_COLLATION_OID
Definition: pg_collation.h:78
#define POSIX_COLLATION_OID
Definition: pg_collation.h:81
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
pg_locale_t pg_newlocale_from_collation ( Oid  collid)

Definition at line 1265 of file pg_locale.c.

References Anum_pg_collation_collversion, Assert, COLLOID, COLLPROVIDER_ICU, COLLPROVIDER_LIBC, DEFAULT_COLLATION_OID, 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(), malloc, NameStr, NULL, ObjectIdGetDatum, OidIsValid, pg_attribute_unused, pg_locale_struct::provider, quote_qualified_identifier(), ReleaseSysCache(), result, SearchSysCache1, status(), SysCacheGetAttr(), TextDatumGetCString, and WARNING.

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

1266 {
1267  collation_cache_entry *cache_entry;
1268 
1269  /* Callers must pass a valid OID */
1270  Assert(OidIsValid(collid));
1271 
1272  /* Return 0 for "default" collation, just in case caller forgets */
1273  if (collid == DEFAULT_COLLATION_OID)
1274  return (pg_locale_t) 0;
1275 
1276  cache_entry = lookup_collation_cache(collid, false);
1277 
1278  if (cache_entry->locale == 0)
1279  {
1280  /* We haven't computed this yet in this session, so do it */
1281  HeapTuple tp;
1282  Form_pg_collation collform;
1283  const char *collcollate;
1284  const char *collctype pg_attribute_unused();
1286  Datum collversion;
1287  bool isnull;
1288 
1289  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1290  if (!HeapTupleIsValid(tp))
1291  elog(ERROR, "cache lookup failed for collation %u", collid);
1292  collform = (Form_pg_collation) GETSTRUCT(tp);
1293 
1294  collcollate = NameStr(collform->collcollate);
1295  collctype = NameStr(collform->collctype);
1296 
1297  result = malloc(sizeof(*result));
1298  memset(result, 0, sizeof(*result));
1299  result->provider = collform->collprovider;
1300 
1301  if (collform->collprovider == COLLPROVIDER_LIBC)
1302  {
1303 #ifdef HAVE_LOCALE_T
1304  locale_t loc;
1305 
1306  if (strcmp(collcollate, collctype) == 0)
1307  {
1308  /* Normal case where they're the same */
1309 #ifndef WIN32
1310  loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1311  NULL);
1312 #else
1313  loc = _create_locale(LC_ALL, collcollate);
1314 #endif
1315  if (!loc)
1316  report_newlocale_failure(collcollate);
1317  }
1318  else
1319  {
1320 #ifndef WIN32
1321  /* We need two newlocale() steps */
1322  locale_t loc1;
1323 
1324  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1325  if (!loc1)
1326  report_newlocale_failure(collcollate);
1327  loc = newlocale(LC_CTYPE_MASK, collctype, loc1);
1328  if (!loc)
1329  report_newlocale_failure(collctype);
1330 #else
1331 
1332  /*
1333  * XXX The _create_locale() API doesn't appear to support
1334  * this. Could perhaps be worked around by changing
1335  * pg_locale_t to contain two separate fields.
1336  */
1337  ereport(ERROR,
1338  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1339  errmsg("collations with different collate and ctype values are not supported on this platform")));
1340 #endif
1341  }
1342 
1343  result->info.lt = loc;
1344 #else /* not HAVE_LOCALE_T */
1345  /* platform that doesn't support locale_t */
1346  ereport(ERROR,
1347  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1348  errmsg("collation provider LIBC is not supported on this platform")));
1349 #endif /* not HAVE_LOCALE_T */
1350  }
1351  else if (collform->collprovider == COLLPROVIDER_ICU)
1352  {
1353 #ifdef USE_ICU
1354  UCollator *collator;
1355  UErrorCode status;
1356 
1357  status = U_ZERO_ERROR;
1358  collator = ucol_open(collcollate, &status);
1359  if (U_FAILURE(status))
1360  ereport(ERROR,
1361  (errmsg("could not open collator for locale \"%s\": %s",
1362  collcollate, u_errorName(status))));
1363 
1364  result->info.icu.locale = strdup(collcollate);
1365  result->info.icu.ucol = collator;
1366 #else /* not USE_ICU */
1367  /* could get here if a collation was created by a build with ICU */
1368  ereport(ERROR,
1369  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1370  errmsg("ICU is not supported in this build"), \
1371  errhint("You need to rebuild PostgreSQL using --with-icu.")));
1372 #endif /* not USE_ICU */
1373  }
1374 
1376  &isnull);
1377  if (!isnull)
1378  {
1379  char *actual_versionstr;
1380  char *collversionstr;
1381 
1382  actual_versionstr = get_collation_actual_version(collform->collprovider, collcollate);
1383  if (!actual_versionstr)
1384  {
1385  /*
1386  * This could happen when specifying a version in CREATE
1387  * COLLATION for a libc locale, or manually creating a mess in
1388  * the catalogs.
1389  */
1390  ereport(ERROR,
1391  (errmsg("collation \"%s\" has no actual version, but a version was specified",
1392  NameStr(collform->collname))));
1393  }
1394  collversionstr = TextDatumGetCString(collversion);
1395 
1396  if (strcmp(actual_versionstr, collversionstr) != 0)
1397  ereport(WARNING,
1398  (errmsg("collation \"%s\" has version mismatch",
1399  NameStr(collform->collname)),
1400  errdetail("The collation in the database was created using version %s, "
1401  "but the operating system provides version %s.",
1402  collversionstr, actual_versionstr),
1403  errhint("Rebuild all objects affected by this collation and run "
1404  "ALTER COLLATION %s REFRESH VERSION, "
1405  "or build PostgreSQL with the right library version.",
1406  quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1407  NameStr(collform->collname)))));
1408  }
1409 
1410  ReleaseSysCache(tp);
1411 
1412  cache_entry->locale = result;
1413  }
1414 
1415  return cache_entry->locale;
1416 }
#define COLLPROVIDER_ICU
Definition: pg_collation.h:85
#define Anum_pg_collation_collversion
Definition: pg_collation.h:66
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define locale_t
Definition: win32.h:323
union pg_locale_struct::@120 info
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1632
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define malloc(a)
Definition: header.h:50
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10370
#define WARNING
Definition: elog.h:40
pg_locale_t locale
Definition: pg_locale.c:125
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
#define pg_attribute_unused()
Definition: c.h:629
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1063
Definition: pg_locale.c:119
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define COLLPROVIDER_LIBC
Definition: pg_collation.h:86
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1427
char* pg_perm_setlocale ( int  category,
const char *  locale 
)

Definition at line 151 of file pg_locale.c.

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

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

152 {
153  char *result;
154  const char *envvar;
155  char *envbuf;
156 
157 #ifndef WIN32
158  result = setlocale(category, locale);
159 #else
160 
161  /*
162  * On Windows, setlocale(LC_MESSAGES) does not work, so just assume that
163  * the given value is good and set it in the environment variables. We
164  * must ignore attempts to set to "", which means "keep using the old
165  * environment value".
166  */
167 #ifdef LC_MESSAGES
168  if (category == LC_MESSAGES)
169  {
170  result = (char *) locale;
171  if (locale == NULL || locale[0] == '\0')
172  return result;
173  }
174  else
175 #endif
176  result = setlocale(category, locale);
177 #endif /* WIN32 */
178 
179  if (result == NULL)
180  return result; /* fall out immediately on failure */
181 
182  /*
183  * Use the right encoding in translated messages. Under ENABLE_NLS, let
184  * pg_bind_textdomain_codeset() figure it out. Under !ENABLE_NLS, message
185  * format strings are ASCII, but database-encoding strings may enter the
186  * message via %s. This makes the overall message encoding equal to the
187  * database encoding.
188  */
189  if (category == LC_CTYPE)
190  {
191  static char save_lc_ctype[LC_ENV_BUFSIZE];
192 
193  /* copy setlocale() return value before callee invokes it again */
194  strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
195  result = save_lc_ctype;
196 
197 #ifdef ENABLE_NLS
198  SetMessageEncoding(pg_bind_textdomain_codeset(textdomain(NULL)));
199 #else
201 #endif
202  }
203 
204  switch (category)
205  {
206  case LC_COLLATE:
207  envvar = "LC_COLLATE";
208  envbuf = lc_collate_envbuf;
209  break;
210  case LC_CTYPE:
211  envvar = "LC_CTYPE";
212  envbuf = lc_ctype_envbuf;
213  break;
214 #ifdef LC_MESSAGES
215  case LC_MESSAGES:
216  envvar = "LC_MESSAGES";
217  envbuf = lc_messages_envbuf;
218 #ifdef WIN32
219  result = IsoLocaleName(locale);
220  if (result == NULL)
221  result = (char *) locale;
222 #endif /* WIN32 */
223  break;
224 #endif /* LC_MESSAGES */
225  case LC_MONETARY:
226  envvar = "LC_MONETARY";
227  envbuf = lc_monetary_envbuf;
228  break;
229  case LC_NUMERIC:
230  envvar = "LC_NUMERIC";
231  envbuf = lc_numeric_envbuf;
232  break;
233  case LC_TIME:
234  envvar = "LC_TIME";
235  envbuf = lc_time_envbuf;
236  break;
237  default:
238  elog(FATAL, "unrecognized LC category: %d", category);
239  envvar = NULL; /* keep compiler quiet */
240  envbuf = NULL;
241  return NULL;
242  }
243 
244  snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
245 
246  if (putenv(envbuf))
247  return NULL;
248 
249  return result;
250 }
static char lc_numeric_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:114
void SetMessageEncoding(int encoding)
Definition: mbutils.c:919
static char lc_monetary_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:113
#define LC_ENV_BUFSIZE
Definition: pg_locale.c:105
return result
Definition: formatting.c:1632
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define putenv(x)
Definition: win32.h:411
static char lc_time_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:115
#define FATAL
Definition: elog.h:52
static char lc_ctype_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:108
int GetDatabaseEncoding(void)
Definition: mbutils.c:1015
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define NULL
Definition: c.h:229
static char * locale
Definition: initdb.c:123
#define elog
Definition: elog.h:219
static char lc_collate_envbuf[LC_ENV_BUFSIZE]
Definition: pg_locale.c:107
struct lconv* PGLC_localeconv ( void  )

Definition at line 483 of file pg_locale.c.

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

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

484 {
485  static struct lconv CurrentLocaleConv;
486  static bool CurrentLocaleConvAllocated = false;
487  struct lconv *extlconv;
488  struct lconv worklconv;
489  bool trouble = false;
490  char *save_lc_monetary;
491  char *save_lc_numeric;
492 #ifdef WIN32
493  char *save_lc_ctype;
494 #endif
495 
496  /* Did we do it already? */
498  return &CurrentLocaleConv;
499 
500  /* Free any already-allocated storage */
501  if (CurrentLocaleConvAllocated)
502  {
503  free_struct_lconv(&CurrentLocaleConv);
504  CurrentLocaleConvAllocated = false;
505  }
506 
507  /*
508  * This is tricky because we really don't want to risk throwing error
509  * while the locale is set to other than our usual settings. Therefore,
510  * the process is: collect the usual settings, set locale to special
511  * setting, copy relevant data into worklconv using strdup(), restore
512  * normal settings, convert data to desired encoding, and finally stash
513  * the collected data in CurrentLocaleConv. This makes it safe if we
514  * throw an error during encoding conversion or run out of memory anywhere
515  * in the process. All data pointed to by struct lconv members is
516  * allocated with strdup, to avoid premature elog(ERROR) and to allow
517  * using a single cleanup routine.
518  */
519  memset(&worklconv, 0, sizeof(worklconv));
520 
521  /* Save user's values of monetary and numeric locales */
522  save_lc_monetary = setlocale(LC_MONETARY, NULL);
523  if (save_lc_monetary)
524  save_lc_monetary = pstrdup(save_lc_monetary);
525 
526  save_lc_numeric = setlocale(LC_NUMERIC, NULL);
527  if (save_lc_numeric)
528  save_lc_numeric = pstrdup(save_lc_numeric);
529 
530 #ifdef WIN32
531 
532  /*
533  * Ideally, monetary and numeric local symbols could be returned in any
534  * server encoding. Unfortunately, the WIN32 API does not allow
535  * setlocale() to return values in a codepage/CTYPE that uses more than
536  * two bytes per character, such as UTF-8:
537  *
538  * http://msdn.microsoft.com/en-us/library/x99tb11d.aspx
539  *
540  * Evidently, LC_CTYPE allows us to control the encoding used for strings
541  * returned by localeconv(). The Open Group standard, mentioned at the
542  * top of this C file, doesn't explicitly state this.
543  *
544  * Therefore, we set LC_CTYPE to match LC_NUMERIC or LC_MONETARY (which
545  * cannot be UTF8), call localeconv(), and then convert from the
546  * numeric/monetary LC_CTYPE to the server encoding. One example use of
547  * this is for the Euro symbol.
548  *
549  * Perhaps someday we will use GetLocaleInfoW() which returns values in
550  * UTF16 and convert from that.
551  */
552 
553  /* save user's value of ctype locale */
554  save_lc_ctype = setlocale(LC_CTYPE, NULL);
555  if (save_lc_ctype)
556  save_lc_ctype = pstrdup(save_lc_ctype);
557 
558  /* Here begins the critical section where we must not throw error */
559 
560  /* use numeric to set the ctype */
561  setlocale(LC_CTYPE, locale_numeric);
562 #endif
563 
564  /* Get formatting information for numeric */
565  setlocale(LC_NUMERIC, locale_numeric);
566  extlconv = localeconv();
567 
568  /* Must copy data now in case setlocale() overwrites it */
569  worklconv.decimal_point = strdup(extlconv->decimal_point);
570  worklconv.thousands_sep = strdup(extlconv->thousands_sep);
571  worklconv.grouping = strdup(extlconv->grouping);
572 
573 #ifdef WIN32
574  /* use monetary to set the ctype */
575  setlocale(LC_CTYPE, locale_monetary);
576 #endif
577 
578  /* Get formatting information for monetary */
579  setlocale(LC_MONETARY, locale_monetary);
580  extlconv = localeconv();
581 
582  /* Must copy data now in case setlocale() overwrites it */
583  worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
584  worklconv.currency_symbol = strdup(extlconv->currency_symbol);
585  worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
586  worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
587  worklconv.mon_grouping = strdup(extlconv->mon_grouping);
588  worklconv.positive_sign = strdup(extlconv->positive_sign);
589  worklconv.negative_sign = strdup(extlconv->negative_sign);
590  /* Copy scalar fields as well */
591  worklconv.int_frac_digits = extlconv->int_frac_digits;
592  worklconv.frac_digits = extlconv->frac_digits;
593  worklconv.p_cs_precedes = extlconv->p_cs_precedes;
594  worklconv.p_sep_by_space = extlconv->p_sep_by_space;
595  worklconv.n_cs_precedes = extlconv->n_cs_precedes;
596  worklconv.n_sep_by_space = extlconv->n_sep_by_space;
597  worklconv.p_sign_posn = extlconv->p_sign_posn;
598  worklconv.n_sign_posn = extlconv->n_sign_posn;
599 
600  /* Try to restore internal settings */
601  if (save_lc_monetary)
602  {
603  if (!setlocale(LC_MONETARY, save_lc_monetary))
604  trouble = true;
605  }
606 
607  if (save_lc_numeric)
608  {
609  if (!setlocale(LC_NUMERIC, save_lc_numeric))
610  trouble = true;
611  }
612 
613 #ifdef WIN32
614  /* Try to restore internal ctype settings */
615  if (save_lc_ctype)
616  {
617  if (!setlocale(LC_CTYPE, save_lc_ctype))
618  trouble = true;
619  }
620 #endif
621 
622  /*
623  * At this point we've done our best to clean up, and can call functions
624  * that might possibly throw errors with a clean conscience. But let's
625  * make sure we don't leak any already-strdup'd fields in worklconv.
626  */
627  PG_TRY();
628  {
629  int encoding;
630 
631  /*
632  * Report it if we failed to restore anything. Perhaps this should be
633  * FATAL, rather than continuing with bad locale settings?
634  */
635  if (trouble)
636  elog(WARNING, "failed to restore old locale");
637 
638  /* Release the pstrdup'd locale names */
639  if (save_lc_monetary)
640  pfree(save_lc_monetary);
641  if (save_lc_numeric)
642  pfree(save_lc_numeric);
643 #ifdef WIN32
644  if (save_lc_ctype)
645  pfree(save_lc_ctype);
646 #endif
647 
648  /* If any of the preceding strdup calls failed, complain now. */
649  if (!struct_lconv_is_valid(&worklconv))
650  ereport(ERROR,
651  (errcode(ERRCODE_OUT_OF_MEMORY),
652  errmsg("out of memory")));
653 
654  /*
655  * Now we must perform encoding conversion from whatever's associated
656  * with the locale into the database encoding.
657  */
659 
660  db_encoding_convert(encoding, &worklconv.decimal_point);
661  db_encoding_convert(encoding, &worklconv.thousands_sep);
662  /* grouping is not text and does not require conversion */
663 
665 
666  db_encoding_convert(encoding, &worklconv.int_curr_symbol);
667  db_encoding_convert(encoding, &worklconv.currency_symbol);
668  db_encoding_convert(encoding, &worklconv.mon_decimal_point);
669  db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
670  /* mon_grouping is not text and does not require conversion */
671  db_encoding_convert(encoding, &worklconv.positive_sign);
672  db_encoding_convert(encoding, &worklconv.negative_sign);
673  }
674  PG_CATCH();
675  {
676  free_struct_lconv(&worklconv);
677  PG_RE_THROW();
678  }
679  PG_END_TRY();
680 
681  /*
682  * Everything is good, so save the results.
683  */
684  CurrentLocaleConv = worklconv;
685  CurrentLocaleConvAllocated = true;
686  CurrentLocaleConvValid = true;
687  return &CurrentLocaleConv;
688 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:100
char * pstrdup(const char *in)
Definition: mcxt.c:1077
int errcode(int sqlerrcode)
Definition: elog.c:575
char * locale_numeric
Definition: pg_locale.c:90
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:393
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:433
static char * encoding
Definition: initdb.c:122
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:229
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:422
#define PG_RE_THROW()
Definition: elog.h:314
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
char * locale_monetary
Definition: pg_locale.c:89
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:453
#define PG_END_TRY()
Definition: elog.h:300

Variable Documentation

char* locale_messages

Definition at line 88 of file pg_locale.c.

char* locale_monetary

Definition at line 89 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_numeric

Definition at line 90 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_time

Definition at line 91 of file pg_locale.c.

Referenced by cache_locale_time().

char* localized_abbrev_days[]

Definition at line 94 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_abbrev_months[]

Definition at line 96 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_days[]

Definition at line 95 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_months[]

Definition at line 97 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().