PostgreSQL Source Code  git master
formatting.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

char * str_tolower (const char *buff, size_t nbytes, Oid collid)
 
char * str_toupper (const char *buff, size_t nbytes, Oid collid)
 
char * str_initcap (const char *buff, size_t nbytes, Oid collid)
 
char * asc_tolower (const char *buff, size_t nbytes)
 
char * asc_toupper (const char *buff, size_t nbytes)
 
char * asc_initcap (const char *buff, size_t nbytes)
 
Datum parse_datetime (text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, bool *have_error)
 

Function Documentation

◆ asc_initcap()

char* asc_initcap ( const char *  buff,
size_t  nbytes 
)

Definition at line 2102 of file formatting.c.

2103 {
2104  char *result;
2105  char *p;
2106  int wasalnum = false;
2107 
2108  if (!buff)
2109  return NULL;
2110 
2111  result = pnstrdup(buff, nbytes);
2112 
2113  for (p = result; *p; p++)
2114  {
2115  char c;
2116 
2117  if (wasalnum)
2118  *p = c = pg_ascii_tolower((unsigned char) *p);
2119  else
2120  *p = c = pg_ascii_toupper((unsigned char) *p);
2121  /* we don't trust isalnum() here */
2122  wasalnum = ((c >= 'A' && c <= 'Z') ||
2123  (c >= 'a' && c <= 'z') ||
2124  (c >= '0' && c <= '9'));
2125  }
2126 
2127  return result;
2128 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1494
unsigned char pg_ascii_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:146
unsigned char pg_ascii_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:135
char * c

References pg_ascii_tolower(), pg_ascii_toupper(), and pnstrdup().

Referenced by str_initcap().

◆ asc_tolower()

char* asc_tolower ( const char *  buff,
size_t  nbytes 
)

Definition at line 2056 of file formatting.c.

2057 {
2058  char *result;
2059  char *p;
2060 
2061  if (!buff)
2062  return NULL;
2063 
2064  result = pnstrdup(buff, nbytes);
2065 
2066  for (p = result; *p; p++)
2067  *p = pg_ascii_tolower((unsigned char) *p);
2068 
2069  return result;
2070 }

References pg_ascii_tolower(), and pnstrdup().

Referenced by asc_tolower_z(), and str_tolower().

◆ asc_toupper()

char* asc_toupper ( const char *  buff,
size_t  nbytes 
)

Definition at line 2079 of file formatting.c.

2080 {
2081  char *result;
2082  char *p;
2083 
2084  if (!buff)
2085  return NULL;
2086 
2087  result = pnstrdup(buff, nbytes);
2088 
2089  for (p = result; *p; p++)
2090  *p = pg_ascii_toupper((unsigned char) *p);
2091 
2092  return result;
2093 }

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

◆ parse_datetime()

Datum parse_datetime ( text date_txt,
text fmt,
Oid  collid,
bool  strict,
Oid typid,
int32 typmod,
int *  tz,
bool have_error 
)

Definition at line 4321 of file formatting.c.

4324 {
4325  struct pg_tm tm;
4326  fsec_t fsec;
4327  int fprec;
4328  uint32 flags;
4329 
4330  do_to_timestamp(date_txt, fmt, collid, strict,
4331  &tm, &fsec, &fprec, &flags, have_error);
4332  CHECK_ERROR;
4333 
4334  *typmod = fprec ? fprec : -1; /* fractional part precision */
4335 
4336  if (flags & DCH_DATED)
4337  {
4338  if (flags & DCH_TIMED)
4339  {
4340  if (flags & DCH_ZONED)
4341  {
4342  TimestampTz result;
4343 
4344  if (tm.tm_zone)
4345  {
4346  int dterr = DecodeTimezone(unconstify(char *, tm.tm_zone), tz);
4347 
4348  if (dterr)
4349  DateTimeParseError(dterr, text_to_cstring(date_txt), "timestamptz");
4350  }
4351  else
4352  {
4353  /*
4354  * Time zone is present in format string, but not in input
4355  * string. Assuming do_to_timestamp() triggers no error
4356  * this should be possible only in non-strict case.
4357  */
4358  Assert(!strict);
4359 
4361  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4362  errmsg("missing time zone in input string for type timestamptz"))));
4363  }
4364 
4365  if (tm2timestamp(&tm, fsec, tz, &result) != 0)
4367  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4368  errmsg("timestamptz out of range"))));
4369 
4370  AdjustTimestampForTypmod(&result, *typmod);
4371 
4372  *typid = TIMESTAMPTZOID;
4373  return TimestampTzGetDatum(result);
4374  }
4375  else
4376  {
4377  Timestamp result;
4378 
4379  if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
4381  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4382  errmsg("timestamp out of range"))));
4383 
4384  AdjustTimestampForTypmod(&result, *typmod);
4385 
4386  *typid = TIMESTAMPOID;
4387  return TimestampGetDatum(result);
4388  }
4389  }
4390  else
4391  {
4392  if (flags & DCH_ZONED)
4393  {
4395  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4396  errmsg("datetime format is zoned but not timed"))));
4397  }
4398  else
4399  {
4400  DateADT result;
4401 
4402  /* Prevent overflow in Julian-day routines */
4405  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4406  errmsg("date out of range: \"%s\"",
4407  text_to_cstring(date_txt)))));
4408 
4409  result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
4411 
4412  /* Now check for just-out-of-range dates */
4413  if (!IS_VALID_DATE(result))
4415  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4416  errmsg("date out of range: \"%s\"",
4417  text_to_cstring(date_txt)))));
4418 
4419  *typid = DATEOID;
4420  return DateADTGetDatum(result);
4421  }
4422  }
4423  }
4424  else if (flags & DCH_TIMED)
4425  {
4426  if (flags & DCH_ZONED)
4427  {
4428  TimeTzADT *result = palloc(sizeof(TimeTzADT));
4429 
4430  if (tm.tm_zone)
4431  {
4432  int dterr = DecodeTimezone(unconstify(char *, tm.tm_zone), tz);
4433 
4434  if (dterr)
4435  RETURN_ERROR(DateTimeParseError(dterr, text_to_cstring(date_txt), "timetz"));
4436  }
4437  else
4438  {
4439  /*
4440  * Time zone is present in format string, but not in input
4441  * string. Assuming do_to_timestamp() triggers no error this
4442  * should be possible only in non-strict case.
4443  */
4444  Assert(!strict);
4445 
4447  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4448  errmsg("missing time zone in input string for type timetz"))));
4449  }
4450 
4451  if (tm2timetz(&tm, fsec, *tz, result) != 0)
4453  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4454  errmsg("timetz out of range"))));
4455 
4456  AdjustTimeForTypmod(&result->time, *typmod);
4457 
4458  *typid = TIMETZOID;
4459  return TimeTzADTPGetDatum(result);
4460  }
4461  else
4462  {
4463  TimeADT result;
4464 
4465  if (tm2time(&tm, fsec, &result) != 0)
4467  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4468  errmsg("time out of range"))));
4469 
4470  AdjustTimeForTypmod(&result, *typmod);
4471 
4472  *typid = TIMEOID;
4473  return TimeADTGetDatum(result);
4474  }
4475  }
4476  else
4477  {
4479  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4480  errmsg("datetime format is not dated and not timed"))));
4481  }
4482 
4483 on_error:
4484  return (Datum) 0;
4485 }
int DecodeTimezone(char *str, int *tzp)
Definition: datetime.c:3148
void DateTimeParseError(int dterr, const char *str, const char *datatype)
Definition: datetime.c:4025
int date2j(int year, int month, int day)
Definition: datetime.c:285
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1926
void AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
Definition: timestamp.c:394
#define unconstify(underlying_type, expr)
Definition: c.h:1181
unsigned int uint32
Definition: c.h:442
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define IS_VALID_DATE(d)
Definition: timestamp.h:229
int32 fsec_t
Definition: timestamp.h:41
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:194
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:202
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1419
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2258
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1648
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
int32 DateADT
Definition: date.h:23
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
Definition: date.h:84
int64 TimeADT
Definition: date.h:25
static Datum TimeADTGetDatum(TimeADT X)
Definition: date.h:78
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
#define CHECK_ERROR
Definition: formatting.c:122
#define DCH_DATED
Definition: formatting.c:1049
#define RETURN_ERROR(throw_error)
Definition: formatting.c:109
#define DCH_TIMED
Definition: formatting.c:1050
static void do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, int *fprec, uint32 *flags, bool *have_error)
Definition: formatting.c:4507
#define DCH_ZONED
Definition: formatting.c:1051
static void const char * fmt
Assert(fmt[strlen(fmt) - 1] !='\n')
static struct pg_tm tm
Definition: localtime.c:104
void * palloc(Size size)
Definition: mcxt.c:1199
uintptr_t Datum
Definition: postgres.h:412
Definition: date.h:28
TimeADT time
Definition: date.h:29
Definition: pgtime.h:35
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
const char * tm_zone
Definition: pgtime.h:46
int tm_year
Definition: pgtime.h:41
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
char * text_to_cstring(const text *t)
Definition: varlena.c:222

References AdjustTimeForTypmod(), AdjustTimestampForTypmod(), Assert(), CHECK_ERROR, date2j(), DateADTGetDatum(), DateTimeParseError(), DCH_DATED, DCH_TIMED, DCH_ZONED, DecodeTimezone(), do_to_timestamp(), ereport, errcode(), errmsg(), ERROR, fmt, IS_VALID_DATE, IS_VALID_JULIAN, palloc(), POSTGRES_EPOCH_JDATE, RETURN_ERROR, text_to_cstring(), TimeTzADT::time, TimeADTGetDatum(), TimestampGetDatum(), TimestampTzGetDatum(), TimeTzADTPGetDatum(), tm, tm2time(), tm2timestamp(), tm2timetz(), pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, pg_tm::tm_zone, and unconstify.

Referenced by executeDateTimeMethod().

◆ str_initcap()

char* str_initcap ( const char *  buff,
size_t  nbytes,
Oid  collid 
)

Definition at line 1909 of file formatting.c.

1910 {
1911  char *result;
1912  int wasalnum = false;
1913 
1914  if (!buff)
1915  return NULL;
1916 
1917  if (!OidIsValid(collid))
1918  {
1919  /*
1920  * This typically means that the parser could not resolve a conflict
1921  * of implicit collations, so report it that way.
1922  */
1923  ereport(ERROR,
1924  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1925  errmsg("could not determine which collation to use for %s function",
1926  "initcap()"),
1927  errhint("Use the COLLATE clause to set the collation explicitly.")));
1928  }
1929 
1930  /* C/POSIX collations use this path regardless of database encoding */
1931  if (lc_ctype_is_c(collid))
1932  {
1933  result = asc_initcap(buff, nbytes);
1934  }
1935  else
1936  {
1937  pg_locale_t mylocale;
1938 
1939  mylocale = pg_newlocale_from_collation(collid);
1940 
1941 #ifdef USE_ICU
1942  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1943  {
1944  int32_t len_uchar,
1945  len_conv;
1946  UChar *buff_uchar;
1947  UChar *buff_conv;
1948 
1949  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1950  len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
1951  &buff_conv, buff_uchar, len_uchar);
1952  icu_from_uchar(&result, buff_conv, len_conv);
1953  pfree(buff_uchar);
1954  pfree(buff_conv);
1955  }
1956  else
1957 #endif
1958  {
1960  {
1961  wchar_t *workspace;
1962  size_t curr_char;
1963  size_t result_size;
1964 
1965  /* Overflow paranoia */
1966  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1967  ereport(ERROR,
1968  (errcode(ERRCODE_OUT_OF_MEMORY),
1969  errmsg("out of memory")));
1970 
1971  /* Output workspace cannot have more codes than input bytes */
1972  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1973 
1974  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1975 
1976  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1977  {
1978 #ifdef HAVE_LOCALE_T
1979  if (mylocale)
1980  {
1981  if (wasalnum)
1982  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1983  else
1984  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1985  wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
1986  }
1987  else
1988 #endif
1989  {
1990  if (wasalnum)
1991  workspace[curr_char] = towlower(workspace[curr_char]);
1992  else
1993  workspace[curr_char] = towupper(workspace[curr_char]);
1994  wasalnum = iswalnum(workspace[curr_char]);
1995  }
1996  }
1997 
1998  /*
1999  * Make result large enough; case change might change number
2000  * of bytes
2001  */
2002  result_size = curr_char * pg_database_encoding_max_length() + 1;
2003  result = palloc(result_size);
2004 
2005  wchar2char(result, workspace, result_size, mylocale);
2006  pfree(workspace);
2007  }
2008  else
2009  {
2010  char *p;
2011 
2012  result = pnstrdup(buff, nbytes);
2013 
2014  /*
2015  * Note: we assume that toupper_l()/tolower_l() will not be so
2016  * broken as to need guard tests. When using the default
2017  * collation, we apply the traditional Postgres behavior that
2018  * forces ASCII-style treatment of I/i, but in non-default
2019  * collations you get exactly what the collation says.
2020  */
2021  for (p = result; *p; p++)
2022  {
2023 #ifdef HAVE_LOCALE_T
2024  if (mylocale)
2025  {
2026  if (wasalnum)
2027  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
2028  else
2029  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
2030  wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
2031  }
2032  else
2033 #endif
2034  {
2035  if (wasalnum)
2036  *p = pg_tolower((unsigned char) *p);
2037  else
2038  *p = pg_toupper((unsigned char) *p);
2039  wasalnum = isalnum((unsigned char) *p);
2040  }
2041  }
2042  }
2043  }
2044  }
2045 
2046  return result;
2047 }
#define OidIsValid(objectId)
Definition: c.h:711
int errhint(const char *fmt,...)
Definition: elog.c:1153
char * asc_initcap(const char *buff, size_t nbytes)
Definition: formatting.c:2102
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1495
void pfree(void *pointer)
Definition: mcxt.c:1306
size_t wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
Definition: pg_locale.c:1990
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1481
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1352
size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
Definition: pg_locale.c:2061
unsigned char pg_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:105
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
union pg_locale_struct::@142 info
#define toupper_l
Definition: win32_port.h:421
#define iswalnum_l
Definition: win32_port.h:429
#define towupper_l
Definition: win32_port.h:423
#define towlower_l
Definition: win32_port.h:422
#define tolower_l
Definition: win32_port.h:420
#define isalnum_l
Definition: win32_port.h:428

References asc_initcap(), char2wchar(), ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, isalnum_l, iswalnum_l, lc_ctype_is_c(), OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), pg_tolower(), pg_toupper(), pnstrdup(), pg_locale_struct::provider, tolower_l, toupper_l, towlower_l, towupper_l, and wchar2char().

Referenced by initcap(), and str_initcap_z().

◆ str_tolower()

char* str_tolower ( const char *  buff,
size_t  nbytes,
Oid  collid 
)

Definition at line 1665 of file formatting.c.

1666 {
1667  char *result;
1668 
1669  if (!buff)
1670  return NULL;
1671 
1672  if (!OidIsValid(collid))
1673  {
1674  /*
1675  * This typically means that the parser could not resolve a conflict
1676  * of implicit collations, so report it that way.
1677  */
1678  ereport(ERROR,
1679  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1680  errmsg("could not determine which collation to use for %s function",
1681  "lower()"),
1682  errhint("Use the COLLATE clause to set the collation explicitly.")));
1683  }
1684 
1685  /* C/POSIX collations use this path regardless of database encoding */
1686  if (lc_ctype_is_c(collid))
1687  {
1688  result = asc_tolower(buff, nbytes);
1689  }
1690  else
1691  {
1692  pg_locale_t mylocale;
1693 
1694  mylocale = pg_newlocale_from_collation(collid);
1695 
1696 #ifdef USE_ICU
1697  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1698  {
1699  int32_t len_uchar;
1700  int32_t len_conv;
1701  UChar *buff_uchar;
1702  UChar *buff_conv;
1703 
1704  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1705  len_conv = icu_convert_case(u_strToLower, mylocale,
1706  &buff_conv, buff_uchar, len_uchar);
1707  icu_from_uchar(&result, buff_conv, len_conv);
1708  pfree(buff_uchar);
1709  pfree(buff_conv);
1710  }
1711  else
1712 #endif
1713  {
1715  {
1716  wchar_t *workspace;
1717  size_t curr_char;
1718  size_t result_size;
1719 
1720  /* Overflow paranoia */
1721  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1722  ereport(ERROR,
1723  (errcode(ERRCODE_OUT_OF_MEMORY),
1724  errmsg("out of memory")));
1725 
1726  /* Output workspace cannot have more codes than input bytes */
1727  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1728 
1729  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1730 
1731  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1732  {
1733 #ifdef HAVE_LOCALE_T
1734  if (mylocale)
1735  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1736  else
1737 #endif
1738  workspace[curr_char] = towlower(workspace[curr_char]);
1739  }
1740 
1741  /*
1742  * Make result large enough; case change might change number
1743  * of bytes
1744  */
1745  result_size = curr_char * pg_database_encoding_max_length() + 1;
1746  result = palloc(result_size);
1747 
1748  wchar2char(result, workspace, result_size, mylocale);
1749  pfree(workspace);
1750  }
1751  else
1752  {
1753  char *p;
1754 
1755  result = pnstrdup(buff, nbytes);
1756 
1757  /*
1758  * Note: we assume that tolower_l() will not be so broken as
1759  * to need an isupper_l() guard test. When using the default
1760  * collation, we apply the traditional Postgres behavior that
1761  * forces ASCII-style treatment of I/i, but in non-default
1762  * collations you get exactly what the collation says.
1763  */
1764  for (p = result; *p; p++)
1765  {
1766 #ifdef HAVE_LOCALE_T
1767  if (mylocale)
1768  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
1769  else
1770 #endif
1771  *p = pg_tolower((unsigned char) *p);
1772  }
1773  }
1774  }
1775  }
1776 
1777  return result;
1778 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2056

References asc_tolower(), char2wchar(), ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, lc_ctype_is_c(), OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), pg_tolower(), pnstrdup(), pg_locale_struct::provider, tolower_l, towlower_l, and wchar2char().

Referenced by citext_eq(), citext_hash(), citext_hash_extended(), citext_ne(), citextcmp(), internal_citext_pattern_cmp(), lower(), ltree_strncasecmp(), seq_search_localized(), and str_tolower_z().

◆ str_toupper()

char* str_toupper ( const char *  buff,
size_t  nbytes,
Oid  collid 
)

Definition at line 1787 of file formatting.c.

1788 {
1789  char *result;
1790 
1791  if (!buff)
1792  return NULL;
1793 
1794  if (!OidIsValid(collid))
1795  {
1796  /*
1797  * This typically means that the parser could not resolve a conflict
1798  * of implicit collations, so report it that way.
1799  */
1800  ereport(ERROR,
1801  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1802  errmsg("could not determine which collation to use for %s function",
1803  "upper()"),
1804  errhint("Use the COLLATE clause to set the collation explicitly.")));
1805  }
1806 
1807  /* C/POSIX collations use this path regardless of database encoding */
1808  if (lc_ctype_is_c(collid))
1809  {
1810  result = asc_toupper(buff, nbytes);
1811  }
1812  else
1813  {
1814  pg_locale_t mylocale;
1815 
1816  mylocale = pg_newlocale_from_collation(collid);
1817 
1818 #ifdef USE_ICU
1819  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1820  {
1821  int32_t len_uchar,
1822  len_conv;
1823  UChar *buff_uchar;
1824  UChar *buff_conv;
1825 
1826  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1827  len_conv = icu_convert_case(u_strToUpper, mylocale,
1828  &buff_conv, buff_uchar, len_uchar);
1829  icu_from_uchar(&result, buff_conv, len_conv);
1830  pfree(buff_uchar);
1831  pfree(buff_conv);
1832  }
1833  else
1834 #endif
1835  {
1837  {
1838  wchar_t *workspace;
1839  size_t curr_char;
1840  size_t result_size;
1841 
1842  /* Overflow paranoia */
1843  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1844  ereport(ERROR,
1845  (errcode(ERRCODE_OUT_OF_MEMORY),
1846  errmsg("out of memory")));
1847 
1848  /* Output workspace cannot have more codes than input bytes */
1849  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1850 
1851  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1852 
1853  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1854  {
1855 #ifdef HAVE_LOCALE_T
1856  if (mylocale)
1857  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1858  else
1859 #endif
1860  workspace[curr_char] = towupper(workspace[curr_char]);
1861  }
1862 
1863  /*
1864  * Make result large enough; case change might change number
1865  * of bytes
1866  */
1867  result_size = curr_char * pg_database_encoding_max_length() + 1;
1868  result = palloc(result_size);
1869 
1870  wchar2char(result, workspace, result_size, mylocale);
1871  pfree(workspace);
1872  }
1873  else
1874  {
1875  char *p;
1876 
1877  result = pnstrdup(buff, nbytes);
1878 
1879  /*
1880  * Note: we assume that toupper_l() will not be so broken as
1881  * to need an islower_l() guard test. When using the default
1882  * collation, we apply the traditional Postgres behavior that
1883  * forces ASCII-style treatment of I/i, but in non-default
1884  * collations you get exactly what the collation says.
1885  */
1886  for (p = result; *p; p++)
1887  {
1888 #ifdef HAVE_LOCALE_T
1889  if (mylocale)
1890  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
1891  else
1892 #endif
1893  *p = pg_toupper((unsigned char) *p);
1894  }
1895  }
1896  }
1897  }
1898 
1899  return result;
1900 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2079

References asc_toupper(), char2wchar(), ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, lc_ctype_is_c(), OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), pg_toupper(), pnstrdup(), pg_locale_struct::provider, toupper_l, towupper_l, and wchar2char().

Referenced by seq_search_localized(), str_toupper_z(), and upper().