PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_locale.c File Reference
#include "postgres.h"
#include <time.h>
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_control.h"
#include "mb/pg_wchar.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/syscache.h"
Include dependency graph for pg_locale.c:

Go to the source code of this file.

Data Structures

struct  collation_cache_entry
 

Macros

#define MAX_L10N_DATA   80
 
#define LC_ENV_BUFSIZE   (NAMEDATALEN + 20)
 

Functions

char * pg_perm_setlocale (int category, const char *locale)
 
bool check_locale (int category, const char *locale, char **canonname)
 
bool check_locale_monetary (char **newval, void **extra, GucSource source)
 
void assign_locale_monetary (const char *newval, void *extra)
 
bool check_locale_numeric (char **newval, void **extra, GucSource source)
 
void assign_locale_numeric (const char *newval, void *extra)
 
bool check_locale_time (char **newval, void **extra, GucSource source)
 
void assign_locale_time (const char *newval, void *extra)
 
bool check_locale_messages (char **newval, void **extra, GucSource source)
 
void assign_locale_messages (const char *newval, void *extra)
 
static void free_struct_lconv (struct lconv *s)
 
static bool struct_lconv_is_valid (struct lconv *s)
 
static void db_encoding_convert (int encoding, char **str)
 
struct lconv * PGLC_localeconv (void)
 
static void cache_single_time (char **dst, const char *format, const struct tm *tm)
 
void cache_locale_time (void)
 
void check_strxfrm_bug (void)
 
static collation_cache_entrylookup_collation_cache (Oid collation, bool set_flags)
 
bool lc_collate_is_c (Oid collation)
 
bool lc_ctype_is_c (Oid collation)
 
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 [7]
 
char * localized_full_days [7]
 
char * localized_abbrev_months [12]
 
char * localized_full_months [12]
 
static bool CurrentLocaleConvValid = false
 
static bool CurrentLCTimeValid = false
 
static char lc_collate_envbuf [LC_ENV_BUFSIZE]
 
static char lc_ctype_envbuf [LC_ENV_BUFSIZE]
 
static char lc_monetary_envbuf [LC_ENV_BUFSIZE]
 
static char lc_numeric_envbuf [LC_ENV_BUFSIZE]
 
static char lc_time_envbuf [LC_ENV_BUFSIZE]
 
static HTABcollation_cache = NULL
 

Macro Definition Documentation

#define LC_ENV_BUFSIZE   (NAMEDATALEN + 20)

Definition at line 99 of file pg_locale.c.

Referenced by pg_perm_setlocale().

#define MAX_L10N_DATA   80

Definition at line 78 of file pg_locale.c.

Referenced by cache_single_time().

Function Documentation

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

Definition at line 370 of file pg_locale.c.

References pg_perm_setlocale().

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

Definition at line 307 of file pg_locale.c.

References CurrentLocaleConvValid.

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

Definition at line 319 of file pg_locale.c.

References CurrentLocaleConvValid.

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

Definition at line 331 of file pg_locale.c.

References CurrentLCTimeValid.

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

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

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

Definition at line 753 of file pg_locale.c.

References buf, elog, ERROR, MAX_L10N_DATA, MemoryContextStrdup(), pfree(), and TopMemoryContext.

Referenced by cache_locale_time().

754 {
755  char buf[MAX_L10N_DATA];
756  char *ptr;
757 
758  /*
759  * MAX_L10N_DATA is sufficient buffer space for every known locale, and
760  * POSIX defines no strftime() errors. (Buffer space exhaustion is not an
761  * error.) An implementation might report errors (e.g. ENOMEM) by
762  * returning 0 (or, less plausibly, a negative value) and setting errno.
763  * Report errno just in case the implementation did that, but clear it in
764  * advance of the call so we don't emit a stale, unrelated errno.
765  */
766  errno = 0;
767  if (strftime(buf, MAX_L10N_DATA, format, tm) <= 0)
768  elog(ERROR, "strftime(%s) failed: %m", format);
769 
771  if (*dst)
772  pfree(*dst);
773  *dst = ptr;
774 }
static struct pg_tm tm
Definition: localtime.c:103
void pfree(void *pointer)
Definition: mcxt.c:992
#define MAX_L10N_DATA
Definition: pg_locale.c:78
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:65
MemoryContext TopMemoryContext
Definition: mcxt.c:43
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1152
static char format
Definition: pg_basebackup.c:82
#define elog
Definition: elog.h:219
bool check_locale ( int  category,
const char *  locale,
char **  canonname 
)

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

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

Definition at line 347 of file pg_locale.c.

References check_locale(), NULL, and PGC_S_DEFAULT.

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

Definition at line 301 of file pg_locale.c.

References check_locale(), and NULL.

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

Definition at line 313 of file pg_locale.c.

References check_locale(), and NULL.

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

Definition at line 325 of file pg_locale.c.

References check_locale(), and NULL.

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

Definition at line 987 of file pg_locale.c.

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

Referenced by CheckMyDatabase(), and main().

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

Definition at line 447 of file pg_locale.c.

References ereport, errcode(), errmsg(), ERROR, free, NULL, pfree(), and pg_any_to_server().

Referenced by PGLC_localeconv().

448 {
449  char *pstr;
450  char *mstr;
451 
452  /* convert the string to the database encoding */
453  pstr = pg_any_to_server(*str, strlen(*str), encoding);
454  if (pstr == *str)
455  return; /* no conversion happened */
456 
457  /* need it malloc'd not palloc'd */
458  mstr = strdup(pstr);
459  if (mstr == NULL)
460  ereport(ERROR,
461  (errcode(ERRCODE_OUT_OF_MEMORY),
462  errmsg("out of memory")));
463 
464  /* replace old string */
465  free(*str);
466  *str = mstr;
467 
468  pfree(pstr);
469 }
int errcode(int sqlerrcode)
Definition: elog.c:575
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static char * encoding
Definition: initdb.c:120
#define free(a)
Definition: header.h:60
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:572
static void free_struct_lconv ( struct lconv *  s)
static

Definition at line 387 of file pg_locale.c.

References free.

Referenced by PGLC_localeconv().

388 {
389  if (s->decimal_point)
390  free(s->decimal_point);
391  if (s->thousands_sep)
392  free(s->thousands_sep);
393  if (s->grouping)
394  free(s->grouping);
395  if (s->int_curr_symbol)
396  free(s->int_curr_symbol);
397  if (s->currency_symbol)
398  free(s->currency_symbol);
399  if (s->mon_decimal_point)
400  free(s->mon_decimal_point);
401  if (s->mon_thousands_sep)
402  free(s->mon_thousands_sep);
403  if (s->mon_grouping)
404  free(s->mon_grouping);
405  if (s->positive_sign)
406  free(s->positive_sign);
407  if (s->negative_sign)
408  free(s->negative_sign);
409 }
#define free(a)
Definition: header.h:60
bool lc_collate_is_c ( Oid  collation)

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

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

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

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

Definition at line 1057 of file pg_locale.c.

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

Referenced by lc_collate_is_c(), lc_ctype_is_c(), and pg_newlocale_from_collation().

1058 {
1059  collation_cache_entry *cache_entry;
1060  bool found;
1061 
1062  Assert(OidIsValid(collation));
1063  Assert(collation != DEFAULT_COLLATION_OID);
1064 
1065  if (collation_cache == NULL)
1066  {
1067  /* First time through, initialize the hash table */
1068  HASHCTL ctl;
1069 
1070  memset(&ctl, 0, sizeof(ctl));
1071  ctl.keysize = sizeof(Oid);
1072  ctl.entrysize = sizeof(collation_cache_entry);
1073  collation_cache = hash_create("Collation cache", 100, &ctl,
1074  HASH_ELEM | HASH_BLOBS);
1075  }
1076 
1077  cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
1078  if (!found)
1079  {
1080  /*
1081  * Make sure cache entry is marked invalid, in case we fail before
1082  * setting things.
1083  */
1084  cache_entry->flags_valid = false;
1085  cache_entry->locale = 0;
1086  }
1087 
1088  if (set_flags && !cache_entry->flags_valid)
1089  {
1090  /* Attempt to set the flags */
1091  HeapTuple tp;
1092  Form_pg_collation collform;
1093  const char *collcollate;
1094  const char *collctype;
1095 
1096  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1097  if (!HeapTupleIsValid(tp))
1098  elog(ERROR, "cache lookup failed for collation %u", collation);
1099  collform = (Form_pg_collation) GETSTRUCT(tp);
1100 
1101  collcollate = NameStr(collform->collcollate);
1102  collctype = NameStr(collform->collctype);
1103 
1104  cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) ||
1105  (strcmp(collcollate, "POSIX") == 0));
1106  cache_entry->ctype_is_c = ((strcmp(collctype, "C") == 0) ||
1107  (strcmp(collctype, "POSIX") == 0));
1108 
1109  cache_entry->flags_valid = true;
1110 
1111  ReleaseSysCache(tp);
1112  }
1113 
1114  return cache_entry;
1115 }
bool flags_valid
Definition: pg_locale.c:118
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define HASH_ELEM
Definition: hsearch.h:87
bool ctype_is_c
Definition: pg_locale.c:117
Size entrysize
Definition: hsearch.h:73
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
bool collate_is_c
Definition: pg_locale.c:116
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:68
pg_locale_t locale
Definition: pg_locale.c:119
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Size keysize
Definition: hsearch.h:72
static HTAB * collation_cache
Definition: pg_locale.c:122
#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
#define NameStr(name)
Definition: c.h:495
#define elog
Definition: elog.h:219
Definition: pg_locale.c:113
pg_locale_t pg_newlocale_from_collation ( Oid  collid)

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

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

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

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

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

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

Definition at line 416 of file pg_locale.c.

References NULL.

Referenced by PGLC_localeconv().

417 {
418  if (s->decimal_point == NULL)
419  return false;
420  if (s->thousands_sep == NULL)
421  return false;
422  if (s->grouping == NULL)
423  return false;
424  if (s->int_curr_symbol == NULL)
425  return false;
426  if (s->currency_symbol == NULL)
427  return false;
428  if (s->mon_decimal_point == NULL)
429  return false;
430  if (s->mon_thousands_sep == NULL)
431  return false;
432  if (s->mon_grouping == NULL)
433  return false;
434  if (s->positive_sign == NULL)
435  return false;
436  if (s->negative_sign == NULL)
437  return false;
438  return true;
439 }
#define NULL
Definition: c.h:226

Variable Documentation

HTAB* collation_cache = NULL
static

Definition at line 122 of file pg_locale.c.

bool CurrentLCTimeValid = false
static

Definition at line 95 of file pg_locale.c.

Referenced by assign_locale_time(), and cache_locale_time().

bool CurrentLocaleConvValid = false
static

Definition at line 94 of file pg_locale.c.

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

char lc_collate_envbuf[LC_ENV_BUFSIZE]
static

Definition at line 101 of file pg_locale.c.

Referenced by pg_perm_setlocale().

char lc_ctype_envbuf[LC_ENV_BUFSIZE]
static

Definition at line 102 of file pg_locale.c.

Referenced by pg_perm_setlocale().

char lc_monetary_envbuf[LC_ENV_BUFSIZE]
static

Definition at line 107 of file pg_locale.c.

Referenced by pg_perm_setlocale().

char lc_numeric_envbuf[LC_ENV_BUFSIZE]
static

Definition at line 108 of file pg_locale.c.

Referenced by pg_perm_setlocale().

char lc_time_envbuf[LC_ENV_BUFSIZE]
static

Definition at line 109 of file pg_locale.c.

Referenced by pg_perm_setlocale().

char* locale_messages

Definition at line 82 of file pg_locale.c.

char* locale_monetary

Definition at line 83 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_numeric

Definition at line 84 of file pg_locale.c.

Referenced by PGLC_localeconv().

char* locale_time

Definition at line 85 of file pg_locale.c.

Referenced by cache_locale_time().

char* localized_abbrev_days[7]

Definition at line 88 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_abbrev_months[12]

Definition at line 90 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_days[7]

Definition at line 89 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().

char* localized_full_months[12]

Definition at line 91 of file pg_locale.c.

Referenced by cache_locale_time(), and DCH_to_char().