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, struct Node *escontext)
 

Function Documentation

◆ asc_initcap()

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

Definition at line 2068 of file formatting.c.

2069 {
2070  char *result;
2071  char *p;
2072  int wasalnum = false;
2073 
2074  if (!buff)
2075  return NULL;
2076 
2077  result = pnstrdup(buff, nbytes);
2078 
2079  for (p = result; *p; p++)
2080  {
2081  char c;
2082 
2083  if (wasalnum)
2084  *p = c = pg_ascii_tolower((unsigned char) *p);
2085  else
2086  *p = c = pg_ascii_toupper((unsigned char) *p);
2087  /* we don't trust isalnum() here */
2088  wasalnum = ((c >= 'A' && c <= 'Z') ||
2089  (c >= 'a' && c <= 'z') ||
2090  (c >= '0' && c <= '9'));
2091  }
2092 
2093  return result;
2094 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1635
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 2022 of file formatting.c.

2023 {
2024  char *result;
2025  char *p;
2026 
2027  if (!buff)
2028  return NULL;
2029 
2030  result = pnstrdup(buff, nbytes);
2031 
2032  for (p = result; *p; p++)
2033  *p = pg_ascii_tolower((unsigned char) *p);
2034 
2035  return result;
2036 }

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 2045 of file formatting.c.

2046 {
2047  char *result;
2048  char *p;
2049 
2050  if (!buff)
2051  return NULL;
2052 
2053  result = pnstrdup(buff, nbytes);
2054 
2055  for (p = result; *p; p++)
2056  *p = pg_ascii_toupper((unsigned char) *p);
2057 
2058  return result;
2059 }

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,
struct Node escontext 
)

Definition at line 4272 of file formatting.c.

4275 {
4276  struct pg_tm tm;
4277  fsec_t fsec;
4278  int fprec;
4279  uint32 flags;
4280 
4281  if (!do_to_timestamp(date_txt, fmt, collid, strict,
4282  &tm, &fsec, &fprec, &flags, escontext))
4283  return (Datum) 0;
4284 
4285  *typmod = fprec ? fprec : -1; /* fractional part precision */
4286 
4287  if (flags & DCH_DATED)
4288  {
4289  if (flags & DCH_TIMED)
4290  {
4291  if (flags & DCH_ZONED)
4292  {
4293  TimestampTz result;
4294 
4295  if (tm.tm_zone)
4296  {
4297  DateTimeErrorExtra extra;
4298  int dterr = DecodeTimezone(tm.tm_zone, tz);
4299 
4300  if (dterr)
4301  {
4302  DateTimeParseError(dterr, &extra,
4303  text_to_cstring(date_txt),
4304  "timestamptz", escontext);
4305  return (Datum) 0;
4306  }
4307  }
4308  else
4309  {
4310  /*
4311  * Time zone is present in format string, but not in input
4312  * string. Assuming do_to_timestamp() triggers no error
4313  * this should be possible only in non-strict case.
4314  */
4315  Assert(!strict);
4316 
4317  ereturn(escontext, (Datum) 0,
4318  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4319  errmsg("missing time zone in input string for type timestamptz")));
4320  }
4321 
4322  if (tm2timestamp(&tm, fsec, tz, &result) != 0)
4323  ereturn(escontext, (Datum) 0,
4324  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4325  errmsg("timestamptz out of range")));
4326 
4327  AdjustTimestampForTypmod(&result, *typmod, escontext);
4328 
4329  *typid = TIMESTAMPTZOID;
4330  return TimestampTzGetDatum(result);
4331  }
4332  else
4333  {
4334  Timestamp result;
4335 
4336  if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
4337  ereturn(escontext, (Datum) 0,
4338  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4339  errmsg("timestamp out of range")));
4340 
4341  AdjustTimestampForTypmod(&result, *typmod, escontext);
4342 
4343  *typid = TIMESTAMPOID;
4344  return TimestampGetDatum(result);
4345  }
4346  }
4347  else
4348  {
4349  if (flags & DCH_ZONED)
4350  {
4351  ereturn(escontext, (Datum) 0,
4352  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4353  errmsg("datetime format is zoned but not timed")));
4354  }
4355  else
4356  {
4357  DateADT result;
4358 
4359  /* Prevent overflow in Julian-day routines */
4361  ereturn(escontext, (Datum) 0,
4362  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4363  errmsg("date out of range: \"%s\"",
4364  text_to_cstring(date_txt))));
4365 
4366  result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
4368 
4369  /* Now check for just-out-of-range dates */
4370  if (!IS_VALID_DATE(result))
4371  ereturn(escontext, (Datum) 0,
4372  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4373  errmsg("date out of range: \"%s\"",
4374  text_to_cstring(date_txt))));
4375 
4376  *typid = DATEOID;
4377  return DateADTGetDatum(result);
4378  }
4379  }
4380  }
4381  else if (flags & DCH_TIMED)
4382  {
4383  if (flags & DCH_ZONED)
4384  {
4385  TimeTzADT *result = palloc(sizeof(TimeTzADT));
4386 
4387  if (tm.tm_zone)
4388  {
4389  DateTimeErrorExtra extra;
4390  int dterr = DecodeTimezone(tm.tm_zone, tz);
4391 
4392  if (dterr)
4393  {
4394  DateTimeParseError(dterr, &extra,
4395  text_to_cstring(date_txt),
4396  "timetz", escontext);
4397  return (Datum) 0;
4398  }
4399  }
4400  else
4401  {
4402  /*
4403  * Time zone is present in format string, but not in input
4404  * string. Assuming do_to_timestamp() triggers no error this
4405  * should be possible only in non-strict case.
4406  */
4407  Assert(!strict);
4408 
4409  ereturn(escontext, (Datum) 0,
4410  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4411  errmsg("missing time zone in input string for type timetz")));
4412  }
4413 
4414  if (tm2timetz(&tm, fsec, *tz, result) != 0)
4415  ereturn(escontext, (Datum) 0,
4416  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4417  errmsg("timetz out of range")));
4418 
4419  AdjustTimeForTypmod(&result->time, *typmod);
4420 
4421  *typid = TIMETZOID;
4422  return TimeTzADTPGetDatum(result);
4423  }
4424  else
4425  {
4426  TimeADT result;
4427 
4428  if (tm2time(&tm, fsec, &result) != 0)
4429  ereturn(escontext, (Datum) 0,
4430  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4431  errmsg("time out of range")));
4432 
4433  AdjustTimeForTypmod(&result, *typmod);
4434 
4435  *typid = TIMEOID;
4436  return TimeADTGetDatum(result);
4437  }
4438  }
4439  else
4440  {
4441  ereturn(escontext, (Datum) 0,
4442  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4443  errmsg("datetime format is not dated and not timed")));
4444  }
4445 }
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:3967
int DecodeTimezone(const char *str, int *tzp)
Definition: datetime.c:2998
int date2j(int year, int month, int day)
Definition: datetime.c:288
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:349
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1934
unsigned int uint32
Definition: c.h:490
Oid collid
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define IS_VALID_DATE(d)
Definition: timestamp.h:236
int32 fsec_t
Definition: timestamp.h:41
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:201
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1424
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2263
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1653
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:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define DCH_DATED
Definition: formatting.c:1015
#define DCH_TIMED
Definition: formatting.c:1016
#define DCH_ZONED
Definition: formatting.c:1017
static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, int *fprec, uint32 *flags, Node *escontext)
Definition: formatting.c:4471
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:1210
uintptr_t Datum
Definition: postgres.h:64
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:215

References AdjustTimeForTypmod(), AdjustTimestampForTypmod(), Assert(), collid, date2j(), DateADTGetDatum(), DateTimeParseError(), DCH_DATED, DCH_TIMED, DCH_ZONED, DecodeTimezone(), do_to_timestamp(), ereturn, errcode(), errmsg(), fmt, IS_VALID_DATE, IS_VALID_JULIAN, palloc(), POSTGRES_EPOCH_JDATE, 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, and pg_tm::tm_zone.

Referenced by executeDateTimeMethod().

◆ str_initcap()

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

Definition at line 1875 of file formatting.c.

1876 {
1877  char *result;
1878  int wasalnum = false;
1879 
1880  if (!buff)
1881  return NULL;
1882 
1883  if (!OidIsValid(collid))
1884  {
1885  /*
1886  * This typically means that the parser could not resolve a conflict
1887  * of implicit collations, so report it that way.
1888  */
1889  ereport(ERROR,
1890  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1891  errmsg("could not determine which collation to use for %s function",
1892  "initcap()"),
1893  errhint("Use the COLLATE clause to set the collation explicitly.")));
1894  }
1895 
1896  /* C/POSIX collations use this path regardless of database encoding */
1897  if (lc_ctype_is_c(collid))
1898  {
1899  result = asc_initcap(buff, nbytes);
1900  }
1901  else
1902  {
1903  pg_locale_t mylocale;
1904 
1905  mylocale = pg_newlocale_from_collation(collid);
1906 
1907 #ifdef USE_ICU
1908  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1909  {
1910  int32_t len_uchar,
1911  len_conv;
1912  UChar *buff_uchar;
1913  UChar *buff_conv;
1914 
1915  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1916  len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
1917  &buff_conv, buff_uchar, len_uchar);
1918  icu_from_uchar(&result, buff_conv, len_conv);
1919  pfree(buff_uchar);
1920  pfree(buff_conv);
1921  }
1922  else
1923 #endif
1924  {
1926  {
1927  wchar_t *workspace;
1928  size_t curr_char;
1929  size_t result_size;
1930 
1931  /* Overflow paranoia */
1932  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1933  ereport(ERROR,
1934  (errcode(ERRCODE_OUT_OF_MEMORY),
1935  errmsg("out of memory")));
1936 
1937  /* Output workspace cannot have more codes than input bytes */
1938  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1939 
1940  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1941 
1942  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1943  {
1944 #ifdef HAVE_LOCALE_T
1945  if (mylocale)
1946  {
1947  if (wasalnum)
1948  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1949  else
1950  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1951  wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
1952  }
1953  else
1954 #endif
1955  {
1956  if (wasalnum)
1957  workspace[curr_char] = towlower(workspace[curr_char]);
1958  else
1959  workspace[curr_char] = towupper(workspace[curr_char]);
1960  wasalnum = iswalnum(workspace[curr_char]);
1961  }
1962  }
1963 
1964  /*
1965  * Make result large enough; case change might change number
1966  * of bytes
1967  */
1968  result_size = curr_char * pg_database_encoding_max_length() + 1;
1969  result = palloc(result_size);
1970 
1971  wchar2char(result, workspace, result_size, mylocale);
1972  pfree(workspace);
1973  }
1974  else
1975  {
1976  char *p;
1977 
1978  result = pnstrdup(buff, nbytes);
1979 
1980  /*
1981  * Note: we assume that toupper_l()/tolower_l() will not be so
1982  * broken as to need guard tests. When using the default
1983  * collation, we apply the traditional Postgres behavior that
1984  * forces ASCII-style treatment of I/i, but in non-default
1985  * collations you get exactly what the collation says.
1986  */
1987  for (p = result; *p; p++)
1988  {
1989 #ifdef HAVE_LOCALE_T
1990  if (mylocale)
1991  {
1992  if (wasalnum)
1993  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
1994  else
1995  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
1996  wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
1997  }
1998  else
1999 #endif
2000  {
2001  if (wasalnum)
2002  *p = pg_tolower((unsigned char) *p);
2003  else
2004  *p = pg_toupper((unsigned char) *p);
2005  wasalnum = isalnum((unsigned char) *p);
2006  }
2007  }
2008  }
2009  }
2010  }
2011 
2012  return result;
2013 }
#define OidIsValid(objectId)
Definition: c.h:759
int errhint(const char *fmt,...)
Definition: elog.c:1316
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * asc_initcap(const char *buff, size_t nbytes)
Definition: formatting.c:2068
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1553
void pfree(void *pointer)
Definition: mcxt.c:1436
size_t wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
Definition: pg_locale.c:2913
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1537
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1377
size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
Definition: pg_locale.c:2984
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:428
#define iswalnum_l
Definition: win32_port.h:436
#define towupper_l
Definition: win32_port.h:430
#define towlower_l
Definition: win32_port.h:429
#define tolower_l
Definition: win32_port.h:427
#define isalnum_l
Definition: win32_port.h:435

References asc_initcap(), char2wchar(), collid, 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 1631 of file formatting.c.

1632 {
1633  char *result;
1634 
1635  if (!buff)
1636  return NULL;
1637 
1638  if (!OidIsValid(collid))
1639  {
1640  /*
1641  * This typically means that the parser could not resolve a conflict
1642  * of implicit collations, so report it that way.
1643  */
1644  ereport(ERROR,
1645  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1646  errmsg("could not determine which collation to use for %s function",
1647  "lower()"),
1648  errhint("Use the COLLATE clause to set the collation explicitly.")));
1649  }
1650 
1651  /* C/POSIX collations use this path regardless of database encoding */
1652  if (lc_ctype_is_c(collid))
1653  {
1654  result = asc_tolower(buff, nbytes);
1655  }
1656  else
1657  {
1658  pg_locale_t mylocale;
1659 
1660  mylocale = pg_newlocale_from_collation(collid);
1661 
1662 #ifdef USE_ICU
1663  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1664  {
1665  int32_t len_uchar;
1666  int32_t len_conv;
1667  UChar *buff_uchar;
1668  UChar *buff_conv;
1669 
1670  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1671  len_conv = icu_convert_case(u_strToLower, mylocale,
1672  &buff_conv, buff_uchar, len_uchar);
1673  icu_from_uchar(&result, buff_conv, len_conv);
1674  pfree(buff_uchar);
1675  pfree(buff_conv);
1676  }
1677  else
1678 #endif
1679  {
1681  {
1682  wchar_t *workspace;
1683  size_t curr_char;
1684  size_t result_size;
1685 
1686  /* Overflow paranoia */
1687  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1688  ereport(ERROR,
1689  (errcode(ERRCODE_OUT_OF_MEMORY),
1690  errmsg("out of memory")));
1691 
1692  /* Output workspace cannot have more codes than input bytes */
1693  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1694 
1695  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1696 
1697  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1698  {
1699 #ifdef HAVE_LOCALE_T
1700  if (mylocale)
1701  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1702  else
1703 #endif
1704  workspace[curr_char] = towlower(workspace[curr_char]);
1705  }
1706 
1707  /*
1708  * Make result large enough; case change might change number
1709  * of bytes
1710  */
1711  result_size = curr_char * pg_database_encoding_max_length() + 1;
1712  result = palloc(result_size);
1713 
1714  wchar2char(result, workspace, result_size, mylocale);
1715  pfree(workspace);
1716  }
1717  else
1718  {
1719  char *p;
1720 
1721  result = pnstrdup(buff, nbytes);
1722 
1723  /*
1724  * Note: we assume that tolower_l() will not be so broken as
1725  * to need an isupper_l() guard test. When using the default
1726  * collation, we apply the traditional Postgres behavior that
1727  * forces ASCII-style treatment of I/i, but in non-default
1728  * collations you get exactly what the collation says.
1729  */
1730  for (p = result; *p; p++)
1731  {
1732 #ifdef HAVE_LOCALE_T
1733  if (mylocale)
1734  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
1735  else
1736 #endif
1737  *p = pg_tolower((unsigned char) *p);
1738  }
1739  }
1740  }
1741  }
1742 
1743  return result;
1744 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2022

References asc_tolower(), char2wchar(), collid, 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 1753 of file formatting.c.

1754 {
1755  char *result;
1756 
1757  if (!buff)
1758  return NULL;
1759 
1760  if (!OidIsValid(collid))
1761  {
1762  /*
1763  * This typically means that the parser could not resolve a conflict
1764  * of implicit collations, so report it that way.
1765  */
1766  ereport(ERROR,
1767  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1768  errmsg("could not determine which collation to use for %s function",
1769  "upper()"),
1770  errhint("Use the COLLATE clause to set the collation explicitly.")));
1771  }
1772 
1773  /* C/POSIX collations use this path regardless of database encoding */
1774  if (lc_ctype_is_c(collid))
1775  {
1776  result = asc_toupper(buff, nbytes);
1777  }
1778  else
1779  {
1780  pg_locale_t mylocale;
1781 
1782  mylocale = pg_newlocale_from_collation(collid);
1783 
1784 #ifdef USE_ICU
1785  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1786  {
1787  int32_t len_uchar,
1788  len_conv;
1789  UChar *buff_uchar;
1790  UChar *buff_conv;
1791 
1792  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1793  len_conv = icu_convert_case(u_strToUpper, mylocale,
1794  &buff_conv, buff_uchar, len_uchar);
1795  icu_from_uchar(&result, buff_conv, len_conv);
1796  pfree(buff_uchar);
1797  pfree(buff_conv);
1798  }
1799  else
1800 #endif
1801  {
1803  {
1804  wchar_t *workspace;
1805  size_t curr_char;
1806  size_t result_size;
1807 
1808  /* Overflow paranoia */
1809  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1810  ereport(ERROR,
1811  (errcode(ERRCODE_OUT_OF_MEMORY),
1812  errmsg("out of memory")));
1813 
1814  /* Output workspace cannot have more codes than input bytes */
1815  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1816 
1817  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1818 
1819  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1820  {
1821 #ifdef HAVE_LOCALE_T
1822  if (mylocale)
1823  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1824  else
1825 #endif
1826  workspace[curr_char] = towupper(workspace[curr_char]);
1827  }
1828 
1829  /*
1830  * Make result large enough; case change might change number
1831  * of bytes
1832  */
1833  result_size = curr_char * pg_database_encoding_max_length() + 1;
1834  result = palloc(result_size);
1835 
1836  wchar2char(result, workspace, result_size, mylocale);
1837  pfree(workspace);
1838  }
1839  else
1840  {
1841  char *p;
1842 
1843  result = pnstrdup(buff, nbytes);
1844 
1845  /*
1846  * Note: we assume that toupper_l() will not be so broken as
1847  * to need an islower_l() guard test. When using the default
1848  * collation, we apply the traditional Postgres behavior that
1849  * forces ASCII-style treatment of I/i, but in non-default
1850  * collations you get exactly what the collation says.
1851  */
1852  for (p = result; *p; p++)
1853  {
1854 #ifdef HAVE_LOCALE_T
1855  if (mylocale)
1856  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
1857  else
1858 #endif
1859  *p = pg_toupper((unsigned char) *p);
1860  }
1861  }
1862  }
1863  }
1864 
1865  return result;
1866 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2045

References asc_toupper(), char2wchar(), collid, 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().