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)
 
bool datetime_format_has_tz (const char *fmt_str)
 

Function Documentation

◆ asc_initcap()

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

Definition at line 2159 of file formatting.c.

2160 {
2161  char *result;
2162  char *p;
2163  int wasalnum = false;
2164 
2165  if (!buff)
2166  return NULL;
2167 
2168  result = pnstrdup(buff, nbytes);
2169 
2170  for (p = result; *p; p++)
2171  {
2172  char c;
2173 
2174  if (wasalnum)
2175  *p = c = pg_ascii_tolower((unsigned char) *p);
2176  else
2177  *p = c = pg_ascii_toupper((unsigned char) *p);
2178  /* we don't trust isalnum() here */
2179  wasalnum = ((c >= 'A' && c <= 'Z') ||
2180  (c >= 'a' && c <= 'z') ||
2181  (c >= '0' && c <= '9'));
2182  }
2183 
2184  return result;
2185 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
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 2113 of file formatting.c.

2114 {
2115  char *result;
2116  char *p;
2117 
2118  if (!buff)
2119  return NULL;
2120 
2121  result = pnstrdup(buff, nbytes);
2122 
2123  for (p = result; *p; p++)
2124  *p = pg_ascii_tolower((unsigned char) *p);
2125 
2126  return result;
2127 }

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

2137 {
2138  char *result;
2139  char *p;
2140 
2141  if (!buff)
2142  return NULL;
2143 
2144  result = pnstrdup(buff, nbytes);
2145 
2146  for (p = result; *p; p++)
2147  *p = pg_ascii_toupper((unsigned char) *p);
2148 
2149  return result;
2150 }

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

◆ datetime_format_has_tz()

bool datetime_format_has_tz ( const char *  fmt_str)

Definition at line 4573 of file formatting.c.

4574 {
4575  bool incache;
4576  int fmt_len = strlen(fmt_str);
4577  int result;
4578  FormatNode *format;
4579 
4580  if (fmt_len > DCH_CACHE_SIZE)
4581  {
4582  /*
4583  * Allocate new memory if format picture is bigger than static cache
4584  * and do not use cache (call parser always)
4585  */
4586  incache = false;
4587 
4588  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4589 
4590  parse_format(format, fmt_str, DCH_keywords,
4591  DCH_suff, DCH_index, DCH_FLAG, NULL);
4592  }
4593  else
4594  {
4595  /*
4596  * Use cache buffers
4597  */
4598  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
4599 
4600  incache = true;
4601  format = ent->format;
4602  }
4603 
4604  result = DCH_datetime_type(format);
4605 
4606  if (!incache)
4607  pfree(format);
4608 
4609  return result & DCH_ZONED;
4610 }
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:948
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num)
Definition: formatting.c:1328
#define DCH_FLAG
Definition: formatting.c:99
static const KeySuffix DCH_suff[]
Definition: formatting.c:568
#define DCH_CACHE_SIZE
Definition: formatting.c:360
#define DCH_ZONED
Definition: formatting.c:1028
static int DCH_datetime_type(FormatNode *node)
Definition: formatting.c:3931
static const KeyWord DCH_keywords[]
Definition: formatting.c:775
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:4109
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
static char format
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:370

References DCH_cache_fetch(), DCH_CACHE_SIZE, DCH_datetime_type(), DCH_FLAG, DCH_index, DCH_keywords, DCH_suff, DCH_ZONED, DCHCacheEntry::format, format, palloc(), parse_format(), and pfree().

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

4413 {
4414  struct pg_tm tm;
4415  struct fmt_tz ftz;
4416  fsec_t fsec;
4417  int fprec;
4418  uint32 flags;
4419 
4420  if (!do_to_timestamp(date_txt, fmt, collid, strict,
4421  &tm, &fsec, &ftz, &fprec, &flags, escontext))
4422  return (Datum) 0;
4423 
4424  *typmod = fprec ? fprec : -1; /* fractional part precision */
4425 
4426  if (flags & DCH_DATED)
4427  {
4428  if (flags & DCH_TIMED)
4429  {
4430  if (flags & DCH_ZONED)
4431  {
4432  TimestampTz result;
4433 
4434  if (ftz.has_tz)
4435  {
4436  *tz = ftz.gmtoffset;
4437  }
4438  else
4439  {
4440  /*
4441  * Time zone is present in format string, but not in input
4442  * string. Assuming do_to_timestamp() triggers no error
4443  * this should be possible only in non-strict case.
4444  */
4445  Assert(!strict);
4446 
4447  ereturn(escontext, (Datum) 0,
4448  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4449  errmsg("missing time zone in input string for type timestamptz")));
4450  }
4451 
4452  if (tm2timestamp(&tm, fsec, tz, &result) != 0)
4453  ereturn(escontext, (Datum) 0,
4454  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4455  errmsg("timestamptz out of range")));
4456 
4457  AdjustTimestampForTypmod(&result, *typmod, escontext);
4458 
4459  *typid = TIMESTAMPTZOID;
4460  return TimestampTzGetDatum(result);
4461  }
4462  else
4463  {
4464  Timestamp result;
4465 
4466  if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
4467  ereturn(escontext, (Datum) 0,
4468  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4469  errmsg("timestamp out of range")));
4470 
4471  AdjustTimestampForTypmod(&result, *typmod, escontext);
4472 
4473  *typid = TIMESTAMPOID;
4474  return TimestampGetDatum(result);
4475  }
4476  }
4477  else
4478  {
4479  if (flags & DCH_ZONED)
4480  {
4481  ereturn(escontext, (Datum) 0,
4482  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4483  errmsg("datetime format is zoned but not timed")));
4484  }
4485  else
4486  {
4487  DateADT result;
4488 
4489  /* Prevent overflow in Julian-day routines */
4491  ereturn(escontext, (Datum) 0,
4492  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4493  errmsg("date out of range: \"%s\"",
4494  text_to_cstring(date_txt))));
4495 
4496  result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
4498 
4499  /* Now check for just-out-of-range dates */
4500  if (!IS_VALID_DATE(result))
4501  ereturn(escontext, (Datum) 0,
4502  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4503  errmsg("date out of range: \"%s\"",
4504  text_to_cstring(date_txt))));
4505 
4506  *typid = DATEOID;
4507  return DateADTGetDatum(result);
4508  }
4509  }
4510  }
4511  else if (flags & DCH_TIMED)
4512  {
4513  if (flags & DCH_ZONED)
4514  {
4515  TimeTzADT *result = palloc(sizeof(TimeTzADT));
4516 
4517  if (ftz.has_tz)
4518  {
4519  *tz = ftz.gmtoffset;
4520  }
4521  else
4522  {
4523  /*
4524  * Time zone is present in format string, but not in input
4525  * string. Assuming do_to_timestamp() triggers no error this
4526  * should be possible only in non-strict case.
4527  */
4528  Assert(!strict);
4529 
4530  ereturn(escontext, (Datum) 0,
4531  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4532  errmsg("missing time zone in input string for type timetz")));
4533  }
4534 
4535  if (tm2timetz(&tm, fsec, *tz, result) != 0)
4536  ereturn(escontext, (Datum) 0,
4537  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4538  errmsg("timetz out of range")));
4539 
4540  AdjustTimeForTypmod(&result->time, *typmod);
4541 
4542  *typid = TIMETZOID;
4543  return TimeTzADTPGetDatum(result);
4544  }
4545  else
4546  {
4547  TimeADT result;
4548 
4549  if (tm2time(&tm, fsec, &result) != 0)
4550  ereturn(escontext, (Datum) 0,
4551  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4552  errmsg("time out of range")));
4553 
4554  AdjustTimeForTypmod(&result, *typmod);
4555 
4556  *typid = TIMEOID;
4557  return TimeADTGetDatum(result);
4558  }
4559  }
4560  else
4561  {
4562  ereturn(escontext, (Datum) 0,
4563  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4564  errmsg("datetime format is not dated and not timed")));
4565  }
4566 }
int date2j(int year, int month, int day)
Definition: datetime.c:286
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:367
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1987
unsigned int uint32
Definition: c.h:492
#define Assert(condition)
Definition: c.h:837
Oid collid
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define IS_VALID_DATE(d)
Definition: timestamp.h:262
int32 fsec_t
Definition: timestamp.h:41
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1428
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2275
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1657
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:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define DCH_DATED
Definition: formatting.c:1026
static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz, int *fprec, uint32 *flags, Node *escontext)
Definition: formatting.c:4636
#define DCH_TIMED
Definition: formatting.c:1027
static void const char * fmt
static struct pg_tm tm
Definition: localtime.c:104
uintptr_t Datum
Definition: postgres.h:64
Definition: date.h:28
TimeADT time
Definition: date.h:29
int gmtoffset
Definition: formatting.c:437
Definition: pgtime.h:35
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
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:217

References AdjustTimeForTypmod(), AdjustTimestampForTypmod(), Assert, collid, date2j(), DateADTGetDatum(), DCH_DATED, DCH_TIMED, DCH_ZONED, do_to_timestamp(), ereturn, errcode(), errmsg(), fmt, fmt_tz::gmtoffset, fmt_tz::has_tz, 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, and pg_tm::tm_year.

Referenced by executeDateTimeMethod().

◆ str_initcap()

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

Definition at line 1951 of file formatting.c.

1952 {
1953  char *result;
1954  int wasalnum = false;
1955  pg_locale_t mylocale;
1956 
1957  if (!buff)
1958  return NULL;
1959 
1960  if (!OidIsValid(collid))
1961  {
1962  /*
1963  * This typically means that the parser could not resolve a conflict
1964  * of implicit collations, so report it that way.
1965  */
1966  ereport(ERROR,
1967  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1968  errmsg("could not determine which collation to use for %s function",
1969  "initcap()"),
1970  errhint("Use the COLLATE clause to set the collation explicitly.")));
1971  }
1972 
1973  mylocale = pg_newlocale_from_collation(collid);
1974 
1975  /* C/POSIX collations use this path regardless of database encoding */
1976  if (mylocale->ctype_is_c)
1977  {
1978  result = asc_initcap(buff, nbytes);
1979  }
1980  else
1981  {
1982 #ifdef USE_ICU
1983  if (mylocale->provider == COLLPROVIDER_ICU)
1984  {
1985  int32_t len_uchar,
1986  len_conv;
1987  UChar *buff_uchar;
1988  UChar *buff_conv;
1989 
1990  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1991  len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
1992  &buff_conv, buff_uchar, len_uchar);
1993  icu_from_uchar(&result, buff_conv, len_conv);
1994  pfree(buff_uchar);
1995  pfree(buff_conv);
1996  }
1997  else
1998 #endif
1999  if (mylocale->provider == COLLPROVIDER_BUILTIN)
2000  {
2001  const char *src = buff;
2002  size_t srclen = nbytes;
2003  size_t dstsize;
2004  char *dst;
2005  size_t needed;
2006  struct WordBoundaryState wbstate = {
2007  .str = src,
2008  .len = srclen,
2009  .offset = 0,
2010  .init = false,
2011  .prev_alnum = false,
2012  };
2013 
2015 
2016  /* first try buffer of equal size plus terminating NUL */
2017  dstsize = srclen + 1;
2018  dst = palloc(dstsize);
2019 
2020  needed = unicode_strtitle(dst, dstsize, src, srclen,
2021  initcap_wbnext, &wbstate);
2022  if (needed + 1 > dstsize)
2023  {
2024  /* reset iterator */
2025  wbstate.offset = 0;
2026  wbstate.init = false;
2027 
2028  /* grow buffer if needed and retry */
2029  dstsize = needed + 1;
2030  dst = repalloc(dst, dstsize);
2031  needed = unicode_strtitle(dst, dstsize, src, srclen,
2032  initcap_wbnext, &wbstate);
2033  Assert(needed + 1 == dstsize);
2034  }
2035 
2036  result = dst;
2037  }
2038  else
2039  {
2040  Assert(mylocale->provider == COLLPROVIDER_LIBC);
2041 
2043  {
2044  wchar_t *workspace;
2045  size_t curr_char;
2046  size_t result_size;
2047 
2048  /* Overflow paranoia */
2049  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
2050  ereport(ERROR,
2051  (errcode(ERRCODE_OUT_OF_MEMORY),
2052  errmsg("out of memory")));
2053 
2054  /* Output workspace cannot have more codes than input bytes */
2055  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
2056 
2057  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
2058 
2059  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
2060  {
2061  if (wasalnum)
2062  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
2063  else
2064  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
2065  wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
2066  }
2067 
2068  /*
2069  * Make result large enough; case change might change number
2070  * of bytes
2071  */
2072  result_size = curr_char * pg_database_encoding_max_length() + 1;
2073  result = palloc(result_size);
2074 
2075  wchar2char(result, workspace, result_size, mylocale);
2076  pfree(workspace);
2077  }
2078  else
2079  {
2080  char *p;
2081 
2082  result = pnstrdup(buff, nbytes);
2083 
2084  /*
2085  * Note: we assume that toupper_l()/tolower_l() will not be so
2086  * broken as to need guard tests. When using the default
2087  * collation, we apply the traditional Postgres behavior that
2088  * forces ASCII-style treatment of I/i, but in non-default
2089  * collations you get exactly what the collation says.
2090  */
2091  for (p = result; *p; p++)
2092  {
2093  if (wasalnum)
2094  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
2095  else
2096  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
2097  wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
2098  }
2099  }
2100  }
2101  }
2102 
2103  return result;
2104 }
#define OidIsValid(objectId)
Definition: c.h:754
int errhint(const char *fmt,...)
Definition: elog.c:1317
#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:2159
static size_t initcap_wbnext(void *state)
Definition: formatting.c:1917
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1546
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1432
size_t wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
@ PG_UTF8
Definition: pg_wchar.h:232
const char * str
Definition: formatting.c:1905
locale_t lt
Definition: pg_locale.h:91
union pg_locale_struct::@156 info
size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, WordBoundaryNext wbnext, void *wbstate)
Definition: unicode_case.c:99
#define toupper_l
Definition: win32_port.h:444
#define iswalnum_l
Definition: win32_port.h:452
#define towupper_l
Definition: win32_port.h:446
#define towlower_l
Definition: win32_port.h:445
#define tolower_l
Definition: win32_port.h:443
#define isalnum_l
Definition: win32_port.h:451

References asc_initcap(), Assert, char2wchar(), collid, pg_locale_struct::ctype_is_c, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, WordBoundaryState::init, initcap_wbnext(), isalnum_l, iswalnum_l, pg_locale_struct::lt, WordBoundaryState::offset, OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), PG_UTF8, pnstrdup(), pg_locale_struct::provider, repalloc(), WordBoundaryState::str, tolower_l, toupper_l, towlower_l, towupper_l, unicode_strtitle(), 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 1636 of file formatting.c.

1637 {
1638  char *result;
1639  pg_locale_t mylocale;
1640 
1641  if (!buff)
1642  return NULL;
1643 
1644  if (!OidIsValid(collid))
1645  {
1646  /*
1647  * This typically means that the parser could not resolve a conflict
1648  * of implicit collations, so report it that way.
1649  */
1650  ereport(ERROR,
1651  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1652  errmsg("could not determine which collation to use for %s function",
1653  "lower()"),
1654  errhint("Use the COLLATE clause to set the collation explicitly.")));
1655  }
1656 
1657  mylocale = pg_newlocale_from_collation(collid);
1658 
1659  /* C/POSIX collations use this path regardless of database encoding */
1660  if (mylocale->ctype_is_c)
1661  {
1662  result = asc_tolower(buff, nbytes);
1663  }
1664  else
1665  {
1666 #ifdef USE_ICU
1667  if (mylocale->provider == COLLPROVIDER_ICU)
1668  {
1669  int32_t len_uchar;
1670  int32_t len_conv;
1671  UChar *buff_uchar;
1672  UChar *buff_conv;
1673 
1674  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1675  len_conv = icu_convert_case(u_strToLower, mylocale,
1676  &buff_conv, buff_uchar, len_uchar);
1677  icu_from_uchar(&result, buff_conv, len_conv);
1678  pfree(buff_uchar);
1679  pfree(buff_conv);
1680  }
1681  else
1682 #endif
1683  if (mylocale->provider == COLLPROVIDER_BUILTIN)
1684  {
1685  const char *src = buff;
1686  size_t srclen = nbytes;
1687  size_t dstsize;
1688  char *dst;
1689  size_t needed;
1690 
1692 
1693  /* first try buffer of equal size plus terminating NUL */
1694  dstsize = srclen + 1;
1695  dst = palloc(dstsize);
1696 
1697  needed = unicode_strlower(dst, dstsize, src, srclen);
1698  if (needed + 1 > dstsize)
1699  {
1700  /* grow buffer if needed and retry */
1701  dstsize = needed + 1;
1702  dst = repalloc(dst, dstsize);
1703  needed = unicode_strlower(dst, dstsize, src, srclen);
1704  Assert(needed + 1 == dstsize);
1705  }
1706 
1707  Assert(dst[needed] == '\0');
1708  result = dst;
1709  }
1710  else
1711  {
1712  Assert(mylocale->provider == COLLPROVIDER_LIBC);
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  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1733 
1734  /*
1735  * Make result large enough; case change might change number
1736  * of bytes
1737  */
1738  result_size = curr_char * pg_database_encoding_max_length() + 1;
1739  result = palloc(result_size);
1740 
1741  wchar2char(result, workspace, result_size, mylocale);
1742  pfree(workspace);
1743  }
1744  else
1745  {
1746  char *p;
1747 
1748  result = pnstrdup(buff, nbytes);
1749 
1750  /*
1751  * Note: we assume that tolower_l() will not be so broken as
1752  * to need an isupper_l() guard test. When using the default
1753  * collation, we apply the traditional Postgres behavior that
1754  * forces ASCII-style treatment of I/i, but in non-default
1755  * collations you get exactly what the collation says.
1756  */
1757  for (p = result; *p; p++)
1758  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
1759  }
1760  }
1761  }
1762 
1763  return result;
1764 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2113
size_t unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen)
Definition: unicode_case.c:68

References asc_tolower(), Assert, char2wchar(), collid, pg_locale_struct::ctype_is_c, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, pg_locale_struct::lt, OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), PG_UTF8, pnstrdup(), pg_locale_struct::provider, repalloc(), tolower_l, towlower_l, unicode_strlower(), 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 1773 of file formatting.c.

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

References asc_toupper(), Assert, char2wchar(), collid, pg_locale_struct::ctype_is_c, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, pg_locale_struct::lt, OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), PG_UTF8, pnstrdup(), pg_locale_struct::provider, repalloc(), toupper_l, towupper_l, unicode_strupper(), and wchar2char().

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