PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_locale.h File Reference
#include <locale.h>
#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.

Typedefs

typedef int pg_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)
 

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

Function Documentation

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

Definition at line 371 of file pg_locale.c.

References pg_perm_setlocale().

372 {
373  /*
374  * LC_MESSAGES category does not exist everywhere, but accept it anyway.
375  * We ignore failure, as per comment above.
376  */
377 #ifdef LC_MESSAGES
378  (void) pg_perm_setlocale(LC_MESSAGES, newval);
379 #endif
380 }
char * pg_perm_setlocale(int category, const char *locale)
Definition: pg_locale.c:146
#define newval
void assign_locale_monetary ( const char *  newval,
void *  extra 
)

Definition at line 308 of file pg_locale.c.

References CurrentLocaleConvValid.

309 {
310  CurrentLocaleConvValid = false;
311 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:95
void assign_locale_numeric ( const char *  newval,
void *  extra 
)

Definition at line 320 of file pg_locale.c.

References CurrentLocaleConvValid.

321 {
322  CurrentLocaleConvValid = false;
323 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:95
void assign_locale_time ( const char *  newval,
void *  extra 
)

Definition at line 332 of file pg_locale.c.

References CurrentLCTimeValid.

333 {
334  CurrentLCTimeValid = false;
335 }
static bool CurrentLCTimeValid
Definition: pg_locale.c:96
void cache_locale_time ( void  )

Definition at line 781 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().

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

Definition at line 259 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().

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

Definition at line 348 of file pg_locale.c.

References check_locale(), NULL, and PGC_S_DEFAULT.

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

Definition at line 302 of file pg_locale.c.

References check_locale(), and NULL.

303 {
304  return check_locale(LC_MONETARY, *newval, NULL);
305 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:259
#define NULL
Definition: c.h:226
#define newval
bool check_locale_numeric ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 314 of file pg_locale.c.

References check_locale(), and NULL.

315 {
316  return check_locale(LC_NUMERIC, *newval, NULL);
317 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:259
#define NULL
Definition: c.h:226
#define newval
bool check_locale_time ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 326 of file pg_locale.c.

References check_locale(), and NULL.

327 {
328  return check_locale(LC_TIME, *newval, NULL);
329 }
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:259
#define NULL
Definition: c.h:226
#define newval
void check_strxfrm_bug ( void  )

Definition at line 988 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

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

Definition at line 1123 of file pg_locale.c.

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

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

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

Definition at line 1173 of file pg_locale.c.

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

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

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

Definition at line 1260 of file pg_locale.c.

References Assert, COLLOID, DEFAULT_COLLATION_OID, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, collation_cache_entry::locale, locale_t, lookup_collation_cache(), NameStr, NULL, ObjectIdGetDatum, OidIsValid, ReleaseSysCache(), and SearchSysCache1.

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

1261 {
1262  collation_cache_entry *cache_entry;
1263 
1264  /* Callers must pass a valid OID */
1265  Assert(OidIsValid(collid));
1266 
1267  /* Return 0 for "default" collation, just in case caller forgets */
1268  if (collid == DEFAULT_COLLATION_OID)
1269  return (pg_locale_t) 0;
1270 
1271  cache_entry = lookup_collation_cache(collid, false);
1272 
1273  if (cache_entry->locale == 0)
1274  {
1275  /* We haven't computed this yet in this session, so do it */
1276 #ifdef HAVE_LOCALE_T
1277  HeapTuple tp;
1278  Form_pg_collation collform;
1279  const char *collcollate;
1280  const char *collctype;
1281  locale_t result;
1282 
1283  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1284  if (!HeapTupleIsValid(tp))
1285  elog(ERROR, "cache lookup failed for collation %u", collid);
1286  collform = (Form_pg_collation) GETSTRUCT(tp);
1287 
1288  collcollate = NameStr(collform->collcollate);
1289  collctype = NameStr(collform->collctype);
1290 
1291  if (strcmp(collcollate, collctype) == 0)
1292  {
1293  /* Normal case where they're the same */
1294 #ifndef WIN32
1295  result = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate,
1296  NULL);
1297 #else
1298  result = _create_locale(LC_ALL, collcollate);
1299 #endif
1300  if (!result)
1301  report_newlocale_failure(collcollate);
1302  }
1303  else
1304  {
1305 #ifndef WIN32
1306  /* We need two newlocale() steps */
1307  locale_t loc1;
1308 
1309  loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL);
1310  if (!loc1)
1311  report_newlocale_failure(collcollate);
1312  result = newlocale(LC_CTYPE_MASK, collctype, loc1);
1313  if (!result)
1314  report_newlocale_failure(collctype);
1315 #else
1316 
1317  /*
1318  * XXX The _create_locale() API doesn't appear to support this.
1319  * Could perhaps be worked around by changing pg_locale_t to
1320  * contain two separate fields.
1321  */
1322  ereport(ERROR,
1323  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1324  errmsg("collations with different collate and ctype values are not supported on this platform")));
1325 #endif
1326  }
1327 
1328  cache_entry->locale = result;
1329 
1330  ReleaseSysCache(tp);
1331 #else /* not HAVE_LOCALE_T */
1332 
1333  /*
1334  * For platforms that don't support locale_t, we can't do anything
1335  * with non-default collations.
1336  */
1337  ereport(ERROR,
1338  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1339  errmsg("nondefault collations are not supported on this platform")));
1340 #endif /* not HAVE_LOCALE_T */
1341  }
1342 
1343  return cache_entry->locale;
1344 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define locale_t
Definition: win32.h:333
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:534
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
int pg_locale_t
Definition: pg_locale.h:71
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
#define ereport(elevel, rest)
Definition: elog.h:122
pg_locale_t locale
Definition: pg_locale.c:120
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:495
#define elog
Definition: elog.h:219
static collation_cache_entry * lookup_collation_cache(Oid collation, bool set_flags)
Definition: pg_locale.c:1058
Definition: pg_locale.c:114
char* pg_perm_setlocale ( int  category,
const char *  locale 
)

Definition at line 146 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, SetMessageEncoding(), snprintf(), and strlcpy().

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

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

Definition at line 478 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().

479 {
480  static struct lconv CurrentLocaleConv;
481  static bool CurrentLocaleConvAllocated = false;
482  struct lconv *extlconv;
483  struct lconv worklconv;
484  bool trouble = false;
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 user's values of monetary and numeric locales */
517  save_lc_monetary = setlocale(LC_MONETARY, NULL);
518  if (save_lc_monetary)
519  save_lc_monetary = pstrdup(save_lc_monetary);
520 
521  save_lc_numeric = setlocale(LC_NUMERIC, NULL);
522  if (save_lc_numeric)
523  save_lc_numeric = pstrdup(save_lc_numeric);
524 
525 #ifdef WIN32
526 
527  /*
528  * Ideally, monetary and numeric local symbols could be returned in any
529  * server encoding. Unfortunately, the WIN32 API does not allow
530  * setlocale() to return values in a codepage/CTYPE that uses more than
531  * two bytes per character, such as UTF-8:
532  *
533  * http://msdn.microsoft.com/en-us/library/x99tb11d.aspx
534  *
535  * Evidently, LC_CTYPE allows us to control the encoding used for strings
536  * returned by localeconv(). The Open Group standard, mentioned at the
537  * top of this C file, doesn't explicitly state this.
538  *
539  * Therefore, we set LC_CTYPE to match LC_NUMERIC or LC_MONETARY (which
540  * cannot be UTF8), call localeconv(), and then convert from the
541  * numeric/monetary LC_CTYPE to the server encoding. One example use of
542  * this is for the Euro symbol.
543  *
544  * Perhaps someday we will use GetLocaleInfoW() which returns values in
545  * UTF16 and convert from that.
546  */
547 
548  /* save user's value of ctype locale */
549  save_lc_ctype = setlocale(LC_CTYPE, NULL);
550  if (save_lc_ctype)
551  save_lc_ctype = pstrdup(save_lc_ctype);
552 
553  /* Here begins the critical section where we must not throw error */
554 
555  /* use numeric to set the ctype */
556  setlocale(LC_CTYPE, locale_numeric);
557 #endif
558 
559  /* Get formatting information for numeric */
560  setlocale(LC_NUMERIC, locale_numeric);
561  extlconv = localeconv();
562 
563  /* Must copy data now in case setlocale() overwrites it */
564  worklconv.decimal_point = strdup(extlconv->decimal_point);
565  worklconv.thousands_sep = strdup(extlconv->thousands_sep);
566  worklconv.grouping = strdup(extlconv->grouping);
567 
568 #ifdef WIN32
569  /* use monetary to set the ctype */
570  setlocale(LC_CTYPE, locale_monetary);
571 #endif
572 
573  /* Get formatting information for monetary */
574  setlocale(LC_MONETARY, locale_monetary);
575  extlconv = localeconv();
576 
577  /* Must copy data now in case setlocale() overwrites it */
578  worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
579  worklconv.currency_symbol = strdup(extlconv->currency_symbol);
580  worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
581  worklconv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
582  worklconv.mon_grouping = strdup(extlconv->mon_grouping);
583  worklconv.positive_sign = strdup(extlconv->positive_sign);
584  worklconv.negative_sign = strdup(extlconv->negative_sign);
585  /* Copy scalar fields as well */
586  worklconv.int_frac_digits = extlconv->int_frac_digits;
587  worklconv.frac_digits = extlconv->frac_digits;
588  worklconv.p_cs_precedes = extlconv->p_cs_precedes;
589  worklconv.p_sep_by_space = extlconv->p_sep_by_space;
590  worklconv.n_cs_precedes = extlconv->n_cs_precedes;
591  worklconv.n_sep_by_space = extlconv->n_sep_by_space;
592  worklconv.p_sign_posn = extlconv->p_sign_posn;
593  worklconv.n_sign_posn = extlconv->n_sign_posn;
594 
595  /* Try to restore internal settings */
596  if (save_lc_monetary)
597  {
598  if (!setlocale(LC_MONETARY, save_lc_monetary))
599  trouble = true;
600  }
601 
602  if (save_lc_numeric)
603  {
604  if (!setlocale(LC_NUMERIC, save_lc_numeric))
605  trouble = true;
606  }
607 
608 #ifdef WIN32
609  /* Try to restore internal ctype settings */
610  if (save_lc_ctype)
611  {
612  if (!setlocale(LC_CTYPE, save_lc_ctype))
613  trouble = true;
614  }
615 #endif
616 
617  /*
618  * At this point we've done our best to clean up, and can call functions
619  * that might possibly throw errors with a clean conscience. But let's
620  * make sure we don't leak any already-strdup'd fields in worklconv.
621  */
622  PG_TRY();
623  {
624  int encoding;
625 
626  /*
627  * Report it if we failed to restore anything. Perhaps this should be
628  * FATAL, rather than continuing with bad locale settings?
629  */
630  if (trouble)
631  elog(WARNING, "failed to restore old locale");
632 
633  /* Release the pstrdup'd locale names */
634  if (save_lc_monetary)
635  pfree(save_lc_monetary);
636  if (save_lc_numeric)
637  pfree(save_lc_numeric);
638 #ifdef WIN32
639  if (save_lc_ctype)
640  pfree(save_lc_ctype);
641 #endif
642 
643  /* If any of the preceding strdup calls failed, complain now. */
644  if (!struct_lconv_is_valid(&worklconv))
645  ereport(ERROR,
646  (errcode(ERRCODE_OUT_OF_MEMORY),
647  errmsg("out of memory")));
648 
649  /*
650  * Now we must perform encoding conversion from whatever's associated
651  * with the locale into the database encoding.
652  */
654 
655  db_encoding_convert(encoding, &worklconv.decimal_point);
656  db_encoding_convert(encoding, &worklconv.thousands_sep);
657  /* grouping is not text and does not require conversion */
658 
660 
661  db_encoding_convert(encoding, &worklconv.int_curr_symbol);
662  db_encoding_convert(encoding, &worklconv.currency_symbol);
663  db_encoding_convert(encoding, &worklconv.mon_decimal_point);
664  db_encoding_convert(encoding, &worklconv.mon_thousands_sep);
665  /* mon_grouping is not text and does not require conversion */
666  db_encoding_convert(encoding, &worklconv.positive_sign);
667  db_encoding_convert(encoding, &worklconv.negative_sign);
668  }
669  PG_CATCH();
670  {
671  free_struct_lconv(&worklconv);
672  PG_RE_THROW();
673  }
674  PG_END_TRY();
675 
676  /*
677  * Everything is good, so save the results.
678  */
679  CurrentLocaleConv = worklconv;
680  CurrentLocaleConvAllocated = true;
681  CurrentLocaleConvValid = true;
682  return &CurrentLocaleConv;
683 }
static bool CurrentLocaleConvValid
Definition: pg_locale.c:95
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int errcode(int sqlerrcode)
Definition: elog.c:575
char * locale_numeric
Definition: pg_locale.c:85
static void free_struct_lconv(struct lconv *s)
Definition: pg_locale.c:388
void pfree(void *pointer)
Definition: mcxt.c:992
#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:438
static char * encoding
Definition: initdb.c:121
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
static bool struct_lconv_is_valid(struct lconv *s)
Definition: pg_locale.c:417
#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:84
static void db_encoding_convert(int encoding, char **str)
Definition: pg_locale.c:448
#define PG_END_TRY()
Definition: elog.h:300

Variable Documentation

char* locale_messages

Definition at line 83 of file pg_locale.c.

char* locale_monetary

Definition at line 84 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_numeric

Definition at line 85 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_time

Definition at line 86 of file pg_locale.c.

Referenced by cache_locale_time().

char* localized_abbrev_days[]

Definition at line 89 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_abbrev_months[]

Definition at line 91 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_days[]

Definition at line 90 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_months[]

Definition at line 92 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().