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

2205 {
2206  char *result;
2207  char *p;
2208  int wasalnum = false;
2209 
2210  if (!buff)
2211  return NULL;
2212 
2213  result = pnstrdup(buff, nbytes);
2214 
2215  for (p = result; *p; p++)
2216  {
2217  char c;
2218 
2219  if (wasalnum)
2220  *p = c = pg_ascii_tolower((unsigned char) *p);
2221  else
2222  *p = c = pg_ascii_toupper((unsigned char) *p);
2223  /* we don't trust isalnum() here */
2224  wasalnum = ((c >= 'A' && c <= 'Z') ||
2225  (c >= 'a' && c <= 'z') ||
2226  (c >= '0' && c <= '9'));
2227  }
2228 
2229  return result;
2230 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1706
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 2158 of file formatting.c.

2159 {
2160  char *result;
2161  char *p;
2162 
2163  if (!buff)
2164  return NULL;
2165 
2166  result = pnstrdup(buff, nbytes);
2167 
2168  for (p = result; *p; p++)
2169  *p = pg_ascii_tolower((unsigned char) *p);
2170 
2171  return result;
2172 }

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

2182 {
2183  char *result;
2184  char *p;
2185 
2186  if (!buff)
2187  return NULL;
2188 
2189  result = pnstrdup(buff, nbytes);
2190 
2191  for (p = result; *p; p++)
2192  *p = pg_ascii_toupper((unsigned char) *p);
2193 
2194  return result;
2195 }

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

4619 {
4620  bool incache;
4621  int fmt_len = strlen(fmt_str);
4622  int result;
4623  FormatNode *format;
4624 
4625  if (fmt_len > DCH_CACHE_SIZE)
4626  {
4627  /*
4628  * Allocate new memory if format picture is bigger than static cache
4629  * and do not use cache (call parser always)
4630  */
4631  incache = false;
4632 
4633  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4634 
4635  parse_format(format, fmt_str, DCH_keywords,
4636  DCH_suff, DCH_index, DCH_FLAG, NULL);
4637  }
4638  else
4639  {
4640  /*
4641  * Use cache buffers
4642  */
4643  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
4644 
4645  incache = true;
4646  format = ent->format;
4647  }
4648 
4649  result = DCH_datetime_type(format);
4650 
4651  if (!incache)
4652  pfree(format);
4653 
4654  return result & DCH_ZONED;
4655 }
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:3976
static const KeyWord DCH_keywords[]
Definition: formatting.c:775
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:4154
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc(Size size)
Definition: mcxt.c:1316
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 4455 of file formatting.c.

4458 {
4459  struct pg_tm tm;
4460  struct fmt_tz ftz;
4461  fsec_t fsec;
4462  int fprec;
4463  uint32 flags;
4464 
4465  if (!do_to_timestamp(date_txt, fmt, collid, strict,
4466  &tm, &fsec, &ftz, &fprec, &flags, escontext))
4467  return (Datum) 0;
4468 
4469  *typmod = fprec ? fprec : -1; /* fractional part precision */
4470 
4471  if (flags & DCH_DATED)
4472  {
4473  if (flags & DCH_TIMED)
4474  {
4475  if (flags & DCH_ZONED)
4476  {
4477  TimestampTz result;
4478 
4479  if (ftz.has_tz)
4480  {
4481  *tz = ftz.gmtoffset;
4482  }
4483  else
4484  {
4485  /*
4486  * Time zone is present in format string, but not in input
4487  * string. Assuming do_to_timestamp() triggers no error
4488  * this should be possible only in non-strict case.
4489  */
4490  Assert(!strict);
4491 
4492  ereturn(escontext, (Datum) 0,
4493  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4494  errmsg("missing time zone in input string for type timestamptz")));
4495  }
4496 
4497  if (tm2timestamp(&tm, fsec, tz, &result) != 0)
4498  ereturn(escontext, (Datum) 0,
4499  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4500  errmsg("timestamptz out of range")));
4501 
4502  AdjustTimestampForTypmod(&result, *typmod, escontext);
4503 
4504  *typid = TIMESTAMPTZOID;
4505  return TimestampTzGetDatum(result);
4506  }
4507  else
4508  {
4509  Timestamp result;
4510 
4511  if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
4512  ereturn(escontext, (Datum) 0,
4513  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4514  errmsg("timestamp out of range")));
4515 
4516  AdjustTimestampForTypmod(&result, *typmod, escontext);
4517 
4518  *typid = TIMESTAMPOID;
4519  return TimestampGetDatum(result);
4520  }
4521  }
4522  else
4523  {
4524  if (flags & DCH_ZONED)
4525  {
4526  ereturn(escontext, (Datum) 0,
4527  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4528  errmsg("datetime format is zoned but not timed")));
4529  }
4530  else
4531  {
4532  DateADT result;
4533 
4534  /* Prevent overflow in Julian-day routines */
4536  ereturn(escontext, (Datum) 0,
4537  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4538  errmsg("date out of range: \"%s\"",
4539  text_to_cstring(date_txt))));
4540 
4541  result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
4543 
4544  /* Now check for just-out-of-range dates */
4545  if (!IS_VALID_DATE(result))
4546  ereturn(escontext, (Datum) 0,
4547  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4548  errmsg("date out of range: \"%s\"",
4549  text_to_cstring(date_txt))));
4550 
4551  *typid = DATEOID;
4552  return DateADTGetDatum(result);
4553  }
4554  }
4555  }
4556  else if (flags & DCH_TIMED)
4557  {
4558  if (flags & DCH_ZONED)
4559  {
4560  TimeTzADT *result = palloc(sizeof(TimeTzADT));
4561 
4562  if (ftz.has_tz)
4563  {
4564  *tz = ftz.gmtoffset;
4565  }
4566  else
4567  {
4568  /*
4569  * Time zone is present in format string, but not in input
4570  * string. Assuming do_to_timestamp() triggers no error this
4571  * should be possible only in non-strict case.
4572  */
4573  Assert(!strict);
4574 
4575  ereturn(escontext, (Datum) 0,
4576  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4577  errmsg("missing time zone in input string for type timetz")));
4578  }
4579 
4580  if (tm2timetz(&tm, fsec, *tz, result) != 0)
4581  ereturn(escontext, (Datum) 0,
4582  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4583  errmsg("timetz out of range")));
4584 
4585  AdjustTimeForTypmod(&result->time, *typmod);
4586 
4587  *typid = TIMETZOID;
4588  return TimeTzADTPGetDatum(result);
4589  }
4590  else
4591  {
4592  TimeADT result;
4593 
4594  if (tm2time(&tm, fsec, &result) != 0)
4595  ereturn(escontext, (Datum) 0,
4596  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4597  errmsg("time out of range")));
4598 
4599  AdjustTimeForTypmod(&result, *typmod);
4600 
4601  *typid = TIMEOID;
4602  return TimeADTGetDatum(result);
4603  }
4604  }
4605  else
4606  {
4607  ereturn(escontext, (Datum) 0,
4608  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4609  errmsg("datetime format is not dated and not timed")));
4610  }
4611 }
int date2j(int year, int month, int day)
Definition: datetime.c:286
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:366
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1997
unsigned int uint32
Definition: c.h:506
#define Assert(condition)
Definition: c.h:858
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:1416
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:1645
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:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#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:4681
#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 1973 of file formatting.c.

1974 {
1975  char *result;
1976  int wasalnum = false;
1977 
1978  if (!buff)
1979  return NULL;
1980 
1981  if (!OidIsValid(collid))
1982  {
1983  /*
1984  * This typically means that the parser could not resolve a conflict
1985  * of implicit collations, so report it that way.
1986  */
1987  ereport(ERROR,
1988  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1989  errmsg("could not determine which collation to use for %s function",
1990  "initcap()"),
1991  errhint("Use the COLLATE clause to set the collation explicitly.")));
1992  }
1993 
1994  /* C/POSIX collations use this path regardless of database encoding */
1995  if (lc_ctype_is_c(collid))
1996  {
1997  result = asc_initcap(buff, nbytes);
1998  }
1999  else
2000  {
2001  pg_locale_t mylocale;
2002 
2003  mylocale = pg_newlocale_from_collation(collid);
2004 
2005 #ifdef USE_ICU
2006  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
2007  {
2008  int32_t len_uchar,
2009  len_conv;
2010  UChar *buff_uchar;
2011  UChar *buff_conv;
2012 
2013  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
2014  len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
2015  &buff_conv, buff_uchar, len_uchar);
2016  icu_from_uchar(&result, buff_conv, len_conv);
2017  pfree(buff_uchar);
2018  pfree(buff_conv);
2019  }
2020  else
2021 #endif
2022  if (mylocale && mylocale->provider == COLLPROVIDER_BUILTIN)
2023  {
2024  const char *src = buff;
2025  size_t srclen = nbytes;
2026  size_t dstsize;
2027  char *dst;
2028  size_t needed;
2029  struct WordBoundaryState wbstate = {
2030  .str = src,
2031  .len = srclen,
2032  .offset = 0,
2033  .init = false,
2034  .prev_alnum = false,
2035  };
2036 
2038 
2039  /* first try buffer of equal size plus terminating NUL */
2040  dstsize = srclen + 1;
2041  dst = palloc(dstsize);
2042 
2043  needed = unicode_strtitle(dst, dstsize, src, srclen,
2044  initcap_wbnext, &wbstate);
2045  if (needed + 1 > dstsize)
2046  {
2047  /* reset iterator */
2048  wbstate.offset = 0;
2049  wbstate.init = false;
2050 
2051  /* grow buffer if needed and retry */
2052  dstsize = needed + 1;
2053  dst = repalloc(dst, dstsize);
2054  needed = unicode_strtitle(dst, dstsize, src, srclen,
2055  initcap_wbnext, &wbstate);
2056  Assert(needed + 1 == dstsize);
2057  }
2058 
2059  result = dst;
2060  }
2061  else
2062  {
2063  Assert(!mylocale || mylocale->provider == COLLPROVIDER_LIBC);
2064 
2066  {
2067  wchar_t *workspace;
2068  size_t curr_char;
2069  size_t result_size;
2070 
2071  /* Overflow paranoia */
2072  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
2073  ereport(ERROR,
2074  (errcode(ERRCODE_OUT_OF_MEMORY),
2075  errmsg("out of memory")));
2076 
2077  /* Output workspace cannot have more codes than input bytes */
2078  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
2079 
2080  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
2081 
2082  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
2083  {
2084  if (mylocale)
2085  {
2086  if (wasalnum)
2087  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
2088  else
2089  workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
2090  wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
2091  }
2092  else
2093  {
2094  if (wasalnum)
2095  workspace[curr_char] = towlower(workspace[curr_char]);
2096  else
2097  workspace[curr_char] = towupper(workspace[curr_char]);
2098  wasalnum = iswalnum(workspace[curr_char]);
2099  }
2100  }
2101 
2102  /*
2103  * Make result large enough; case change might change number
2104  * of bytes
2105  */
2106  result_size = curr_char * pg_database_encoding_max_length() + 1;
2107  result = palloc(result_size);
2108 
2109  wchar2char(result, workspace, result_size, mylocale);
2110  pfree(workspace);
2111  }
2112  else
2113  {
2114  char *p;
2115 
2116  result = pnstrdup(buff, nbytes);
2117 
2118  /*
2119  * Note: we assume that toupper_l()/tolower_l() will not be so
2120  * broken as to need guard tests. When using the default
2121  * collation, we apply the traditional Postgres behavior that
2122  * forces ASCII-style treatment of I/i, but in non-default
2123  * collations you get exactly what the collation says.
2124  */
2125  for (p = result; *p; p++)
2126  {
2127  if (mylocale)
2128  {
2129  if (wasalnum)
2130  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
2131  else
2132  *p = toupper_l((unsigned char) *p, mylocale->info.lt);
2133  wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
2134  }
2135  else
2136  {
2137  if (wasalnum)
2138  *p = pg_tolower((unsigned char) *p);
2139  else
2140  *p = pg_toupper((unsigned char) *p);
2141  wasalnum = isalnum((unsigned char) *p);
2142  }
2143  }
2144  }
2145  }
2146  }
2147 
2148  return result;
2149 }
#define OidIsValid(objectId)
Definition: c.h:775
int errhint(const char *fmt,...)
Definition: elog.c:1319
#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:2204
static size_t initcap_wbnext(void *state)
Definition: formatting.c:1939
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:1540
size_t wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale)
Definition: pg_locale.c:3065
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1551
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1384
size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, pg_locale_t locale)
Definition: pg_locale.c:3121
@ PG_UTF8
Definition: pg_wchar.h:232
unsigned char pg_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:105
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
const char * str
Definition: formatting.c:1927
locale_t lt
Definition: pg_locale.h:83
union pg_locale_struct::@151 info
size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, WordBoundaryNext wbnext, void *wbstate)
Definition: unicode_case.c:100
#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(), Assert, char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), pg_locale_struct::info, WordBoundaryState::init, initcap_wbnext(), isalnum_l, iswalnum_l, lc_ctype_is_c(), pg_locale_struct::lt, WordBoundaryState::offset, OidIsValid, palloc(), pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), pg_tolower(), pg_toupper(), 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 
1640  if (!buff)
1641  return NULL;
1642 
1643  if (!OidIsValid(collid))
1644  {
1645  /*
1646  * This typically means that the parser could not resolve a conflict
1647  * of implicit collations, so report it that way.
1648  */
1649  ereport(ERROR,
1650  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1651  errmsg("could not determine which collation to use for %s function",
1652  "lower()"),
1653  errhint("Use the COLLATE clause to set the collation explicitly.")));
1654  }
1655 
1656  /* C/POSIX collations use this path regardless of database encoding */
1657  if (lc_ctype_is_c(collid))
1658  {
1659  result = asc_tolower(buff, nbytes);
1660  }
1661  else
1662  {
1663  pg_locale_t mylocale;
1664 
1665  mylocale = pg_newlocale_from_collation(collid);
1666 
1667 #ifdef USE_ICU
1668  if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1669  {
1670  int32_t len_uchar;
1671  int32_t len_conv;
1672  UChar *buff_uchar;
1673  UChar *buff_conv;
1674 
1675  len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1676  len_conv = icu_convert_case(u_strToLower, mylocale,
1677  &buff_conv, buff_uchar, len_uchar);
1678  icu_from_uchar(&result, buff_conv, len_conv);
1679  pfree(buff_uchar);
1680  pfree(buff_conv);
1681  }
1682  else
1683 #endif
1684  if (mylocale && mylocale->provider == COLLPROVIDER_BUILTIN)
1685  {
1686  const char *src = buff;
1687  size_t srclen = nbytes;
1688  size_t dstsize;
1689  char *dst;
1690  size_t needed;
1691 
1693 
1694  /* first try buffer of equal size plus terminating NUL */
1695  dstsize = srclen + 1;
1696  dst = palloc(dstsize);
1697 
1698  needed = unicode_strlower(dst, dstsize, src, srclen);
1699  if (needed + 1 > dstsize)
1700  {
1701  /* grow buffer if needed and retry */
1702  dstsize = needed + 1;
1703  dst = repalloc(dst, dstsize);
1704  needed = unicode_strlower(dst, dstsize, src, srclen);
1705  Assert(needed + 1 == dstsize);
1706  }
1707 
1708  Assert(dst[needed] == '\0');
1709  result = dst;
1710  }
1711  else
1712  {
1713  Assert(!mylocale || mylocale->provider == COLLPROVIDER_LIBC);
1714 
1716  {
1717  wchar_t *workspace;
1718  size_t curr_char;
1719  size_t result_size;
1720 
1721  /* Overflow paranoia */
1722  if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1723  ereport(ERROR,
1724  (errcode(ERRCODE_OUT_OF_MEMORY),
1725  errmsg("out of memory")));
1726 
1727  /* Output workspace cannot have more codes than input bytes */
1728  workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1729 
1730  char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1731 
1732  for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1733  {
1734  if (mylocale)
1735  workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1736  else
1737  workspace[curr_char] = towlower(workspace[curr_char]);
1738  }
1739 
1740  /*
1741  * Make result large enough; case change might change number
1742  * of bytes
1743  */
1744  result_size = curr_char * pg_database_encoding_max_length() + 1;
1745  result = palloc(result_size);
1746 
1747  wchar2char(result, workspace, result_size, mylocale);
1748  pfree(workspace);
1749  }
1750  else
1751  {
1752  char *p;
1753 
1754  result = pnstrdup(buff, nbytes);
1755 
1756  /*
1757  * Note: we assume that tolower_l() will not be so broken as
1758  * to need an isupper_l() guard test. When using the default
1759  * collation, we apply the traditional Postgres behavior that
1760  * forces ASCII-style treatment of I/i, but in non-default
1761  * collations you get exactly what the collation says.
1762  */
1763  for (p = result; *p; p++)
1764  {
1765  if (mylocale)
1766  *p = tolower_l((unsigned char) *p, mylocale->info.lt);
1767  else
1768  *p = pg_tolower((unsigned char) *p);
1769  }
1770  }
1771  }
1772  }
1773 
1774  return result;
1775 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2158
size_t unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen)
Definition: unicode_case.c:69

References asc_tolower(), Assert, char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), 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(), 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 1784 of file formatting.c.

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

References asc_toupper(), Assert, char2wchar(), collid, ereport, errcode(), errhint(), errmsg(), ERROR, GetDatabaseEncoding(), 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(), 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().