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

2051 {
2052  char *result;
2053  char *p;
2054  int wasalnum = false;
2055 
2056  if (!buff)
2057  return NULL;
2058 
2059  result = pnstrdup(buff, nbytes);
2060 
2061  for (p = result; *p; p++)
2062  {
2063  char c;
2064 
2065  if (wasalnum)
2066  *p = c = pg_ascii_tolower((unsigned char) *p);
2067  else
2068  *p = c = pg_ascii_toupper((unsigned char) *p);
2069  /* we don't trust isalnum() here */
2070  wasalnum = ((c >= 'A' && c <= 'Z') ||
2071  (c >= 'a' && c <= 'z') ||
2072  (c >= '0' && c <= '9'));
2073  }
2074 
2075  return result;
2076 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1655
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 2004 of file formatting.c.

2005 {
2006  char *result;
2007  char *p;
2008 
2009  if (!buff)
2010  return NULL;
2011 
2012  result = pnstrdup(buff, nbytes);
2013 
2014  for (p = result; *p; p++)
2015  *p = pg_ascii_tolower((unsigned char) *p);
2016 
2017  return result;
2018 }

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

2028 {
2029  char *result;
2030  char *p;
2031 
2032  if (!buff)
2033  return NULL;
2034 
2035  result = pnstrdup(buff, nbytes);
2036 
2037  for (p = result; *p; p++)
2038  *p = pg_ascii_toupper((unsigned char) *p);
2039 
2040  return result;
2041 }

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

4257 {
4258  struct pg_tm tm;
4259  fsec_t fsec;
4260  int fprec;
4261  uint32 flags;
4262 
4263  if (!do_to_timestamp(date_txt, fmt, collid, strict,
4264  &tm, &fsec, &fprec, &flags, escontext))
4265  return (Datum) 0;
4266 
4267  *typmod = fprec ? fprec : -1; /* fractional part precision */
4268 
4269  if (flags & DCH_DATED)
4270  {
4271  if (flags & DCH_TIMED)
4272  {
4273  if (flags & DCH_ZONED)
4274  {
4275  TimestampTz result;
4276 
4277  if (tm.tm_zone)
4278  {
4279  DateTimeErrorExtra extra;
4280  int dterr = DecodeTimezone(tm.tm_zone, tz);
4281 
4282  if (dterr)
4283  {
4284  DateTimeParseError(dterr, &extra,
4285  text_to_cstring(date_txt),
4286  "timestamptz", escontext);
4287  return (Datum) 0;
4288  }
4289  }
4290  else
4291  {
4292  /*
4293  * Time zone is present in format string, but not in input
4294  * string. Assuming do_to_timestamp() triggers no error
4295  * this should be possible only in non-strict case.
4296  */
4297  Assert(!strict);
4298 
4299  ereturn(escontext, (Datum) 0,
4300  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4301  errmsg("missing time zone in input string for type timestamptz")));
4302  }
4303 
4304  if (tm2timestamp(&tm, fsec, tz, &result) != 0)
4305  ereturn(escontext, (Datum) 0,
4306  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4307  errmsg("timestamptz out of range")));
4308 
4309  AdjustTimestampForTypmod(&result, *typmod, escontext);
4310 
4311  *typid = TIMESTAMPTZOID;
4312  return TimestampTzGetDatum(result);
4313  }
4314  else
4315  {
4316  Timestamp result;
4317 
4318  if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
4319  ereturn(escontext, (Datum) 0,
4320  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4321  errmsg("timestamp out of range")));
4322 
4323  AdjustTimestampForTypmod(&result, *typmod, escontext);
4324 
4325  *typid = TIMESTAMPOID;
4326  return TimestampGetDatum(result);
4327  }
4328  }
4329  else
4330  {
4331  if (flags & DCH_ZONED)
4332  {
4333  ereturn(escontext, (Datum) 0,
4334  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4335  errmsg("datetime format is zoned but not timed")));
4336  }
4337  else
4338  {
4339  DateADT result;
4340 
4341  /* Prevent overflow in Julian-day routines */
4343  ereturn(escontext, (Datum) 0,
4344  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4345  errmsg("date out of range: \"%s\"",
4346  text_to_cstring(date_txt))));
4347 
4348  result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
4350 
4351  /* Now check for just-out-of-range dates */
4352  if (!IS_VALID_DATE(result))
4353  ereturn(escontext, (Datum) 0,
4354  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4355  errmsg("date out of range: \"%s\"",
4356  text_to_cstring(date_txt))));
4357 
4358  *typid = DATEOID;
4359  return DateADTGetDatum(result);
4360  }
4361  }
4362  }
4363  else if (flags & DCH_TIMED)
4364  {
4365  if (flags & DCH_ZONED)
4366  {
4367  TimeTzADT *result = palloc(sizeof(TimeTzADT));
4368 
4369  if (tm.tm_zone)
4370  {
4371  DateTimeErrorExtra extra;
4372  int dterr = DecodeTimezone(tm.tm_zone, tz);
4373 
4374  if (dterr)
4375  {
4376  DateTimeParseError(dterr, &extra,
4377  text_to_cstring(date_txt),
4378  "timetz", escontext);
4379  return (Datum) 0;
4380  }
4381  }
4382  else
4383  {
4384  /*
4385  * Time zone is present in format string, but not in input
4386  * string. Assuming do_to_timestamp() triggers no error this
4387  * should be possible only in non-strict case.
4388  */
4389  Assert(!strict);
4390 
4391  ereturn(escontext, (Datum) 0,
4392  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4393  errmsg("missing time zone in input string for type timetz")));
4394  }
4395 
4396  if (tm2timetz(&tm, fsec, *tz, result) != 0)
4397  ereturn(escontext, (Datum) 0,
4398  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4399  errmsg("timetz out of range")));
4400 
4401  AdjustTimeForTypmod(&result->time, *typmod);
4402 
4403  *typid = TIMETZOID;
4404  return TimeTzADTPGetDatum(result);
4405  }
4406  else
4407  {
4408  TimeADT result;
4409 
4410  if (tm2time(&tm, fsec, &result) != 0)
4411  ereturn(escontext, (Datum) 0,
4412  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4413  errmsg("time out of range")));
4414 
4415  AdjustTimeForTypmod(&result, *typmod);
4416 
4417  *typid = TIMEOID;
4418  return TimeADTGetDatum(result);
4419  }
4420  }
4421  else
4422  {
4423  ereturn(escontext, (Datum) 0,
4424  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4425  errmsg("datetime format is not dated and not timed")));
4426  }
4427 }
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:3981
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:350
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1926
unsigned int uint32
Definition: c.h:495
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:1415
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2254
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1644
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:4453
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:1226
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 1861 of file formatting.c.

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

References asc_initcap(), char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, isalnum_l, iswalnum_l, lc_ctype_is_c(), pg_locale_struct::lt, 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 1625 of file formatting.c.

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

References asc_tolower(), char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, lc_ctype_is_c(), pg_locale_struct::lt, 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 1743 of file formatting.c.

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

References asc_toupper(), char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, pg_locale_struct::info, lc_ctype_is_c(), pg_locale_struct::lt, 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().