PostgreSQL Source Code  git master
formatting.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <wchar.h>
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "parser/scansup.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/formatting.h"
#include "utils/int8.h"
#include "utils/memutils.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
Include dependency graph for formatting.c:

Go to the source code of this file.

Data Structures

struct  KeySuffix
 
struct  KeyWord
 
struct  FormatNode
 
struct  NUMDesc
 
struct  DCHCacheEntry
 
struct  NUMCacheEntry
 
struct  TmFromChar
 
struct  TmToChar
 
struct  NUMProc
 

Macros

#define RETURN_ERROR(throw_error)
 
#define CHECK_ERROR
 
#define DCH_FLAG   0x1 /* DATE-TIME flag */
 
#define NUM_FLAG   0x2 /* NUMBER flag */
 
#define STD_FLAG   0x4 /* STANDARD flag */
 
#define KeyWord_INDEX_SIZE   ('~' - ' ')
 
#define KeyWord_INDEX_FILTER(_c)   ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
 
#define DCH_MAX_ITEM_SIZ   12 /* max localized day name */
 
#define NUM_MAX_ITEM_SIZ   8 /* roman number (RN has 15 chars) */
 
#define NODE_TYPE_END   1
 
#define NODE_TYPE_ACTION   2
 
#define NODE_TYPE_CHAR   3
 
#define NODE_TYPE_SEPARATOR   4
 
#define NODE_TYPE_SPACE   5
 
#define SUFFTYPE_PREFIX   1
 
#define SUFFTYPE_POSTFIX   2
 
#define CLOCK_24_HOUR   0
 
#define CLOCK_12_HOUR   1
 
#define ADJUST_YEAR(year, is_interval)   ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
 
#define A_D_STR   "A.D."
 
#define a_d_STR   "a.d."
 
#define AD_STR   "AD"
 
#define ad_STR   "ad"
 
#define B_C_STR   "B.C."
 
#define b_c_STR   "b.c."
 
#define BC_STR   "BC"
 
#define bc_STR   "bc"
 
#define A_M_STR   "A.M."
 
#define a_m_STR   "a.m."
 
#define AM_STR   "AM"
 
#define am_STR   "am"
 
#define P_M_STR   "P.M."
 
#define p_m_STR   "p.m."
 
#define PM_STR   "PM"
 
#define pm_STR   "pm"
 
#define TH_UPPER   1
 
#define TH_LOWER   2
 
#define NUM_F_DECIMAL   (1 << 1)
 
#define NUM_F_LDECIMAL   (1 << 2)
 
#define NUM_F_ZERO   (1 << 3)
 
#define NUM_F_BLANK   (1 << 4)
 
#define NUM_F_FILLMODE   (1 << 5)
 
#define NUM_F_LSIGN   (1 << 6)
 
#define NUM_F_BRACKET   (1 << 7)
 
#define NUM_F_MINUS   (1 << 8)
 
#define NUM_F_PLUS   (1 << 9)
 
#define NUM_F_ROMAN   (1 << 10)
 
#define NUM_F_MULTI   (1 << 11)
 
#define NUM_F_PLUS_POST   (1 << 12)
 
#define NUM_F_MINUS_POST   (1 << 13)
 
#define NUM_F_EEEE   (1 << 14)
 
#define NUM_LSIGN_PRE   (-1)
 
#define NUM_LSIGN_POST   1
 
#define NUM_LSIGN_NONE   0
 
#define IS_DECIMAL(_f)   ((_f)->flag & NUM_F_DECIMAL)
 
#define IS_LDECIMAL(_f)   ((_f)->flag & NUM_F_LDECIMAL)
 
#define IS_ZERO(_f)   ((_f)->flag & NUM_F_ZERO)
 
#define IS_BLANK(_f)   ((_f)->flag & NUM_F_BLANK)
 
#define IS_FILLMODE(_f)   ((_f)->flag & NUM_F_FILLMODE)
 
#define IS_BRACKET(_f)   ((_f)->flag & NUM_F_BRACKET)
 
#define IS_MINUS(_f)   ((_f)->flag & NUM_F_MINUS)
 
#define IS_LSIGN(_f)   ((_f)->flag & NUM_F_LSIGN)
 
#define IS_PLUS(_f)   ((_f)->flag & NUM_F_PLUS)
 
#define IS_ROMAN(_f)   ((_f)->flag & NUM_F_ROMAN)
 
#define IS_MULTI(_f)   ((_f)->flag & NUM_F_MULTI)
 
#define IS_EEEE(_f)   ((_f)->flag & NUM_F_EEEE)
 
#define DCH_CACHE_OVERHEAD   MAXALIGN(sizeof(bool) + sizeof(int))
 
#define NUM_CACHE_OVERHEAD   MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
 
#define DCH_CACHE_SIZE   ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
 
#define NUM_CACHE_SIZE   ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
 
#define DCH_CACHE_ENTRIES   20
 
#define NUM_CACHE_ENTRIES   20
 
#define ZERO_tmfc(_X)   memset(_X, 0, sizeof(TmFromChar))
 
#define DEBUG_TMFC(_X)
 
#define DEBUG_TM(_X)
 
#define tmtcTm(_X)   (&(_X)->tm)
 
#define tmtcTzn(_X)   ((_X)->tzn)
 
#define tmtcFsec(_X)   ((_X)->fsec)
 
#define ZERO_tm(_X)
 
#define ZERO_tmtc(_X)
 
#define INVALID_FOR_INTERVAL
 
#define DCH_S_FM   0x01
 
#define DCH_S_TH   0x02
 
#define DCH_S_th   0x04
 
#define DCH_S_SP   0x08
 
#define DCH_S_TM   0x10
 
#define S_THth(_s)   ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
 
#define S_TH(_s)   (((_s) & DCH_S_TH) ? 1 : 0)
 
#define S_th(_s)   (((_s) & DCH_S_th) ? 1 : 0)
 
#define S_TH_TYPE(_s)   (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
 
#define S_FM(_s)   (((_s) & DCH_S_FM) ? 1 : 0)
 
#define S_SP(_s)   (((_s) & DCH_S_SP) ? 1 : 0)
 
#define S_TM(_s)   (((_s) & DCH_S_TM) ? 1 : 0)
 
#define TM_SUFFIX_LEN   2
 
#define DCH_DATED   0x01
 
#define DCH_TIMED   0x02
 
#define DCH_ZONED   0x04
 
#define SKIP_THth(ptr, _suf)
 
#define DCH_to_char_fsec(frac_fmt, frac_val)
 
#define zeroize_NUM(_n)
 
#define OVERLOAD_TEST   (Np->inout_p >= Np->inout + input_len)
 
#define AMOUNT_TEST(s)   (Np->inout_p <= Np->inout + (input_len - (s)))
 
#define IS_PREDEC_SPACE(_n)
 
#define NUM_TOCHAR_prepare
 
#define NUM_TOCHAR_finish
 

Typedefs

typedef struct TmToChar TmToChar
 
typedef struct NUMProc NUMProc
 

Enumerations

enum  FromCharDateMode { FROM_CHAR_DATE_NONE = 0, FROM_CHAR_DATE_GREGORIAN, FROM_CHAR_DATE_ISOWEEK }
 
enum  DCH_poz {
  DCH_A_D, DCH_A_M, DCH_AD, DCH_AM,
  DCH_B_C, DCH_BC, DCH_CC, DCH_DAY,
  DCH_DDD, DCH_DD, DCH_DY, DCH_Day,
  DCH_Dy, DCH_D, DCH_FF1, DCH_FF2,
  DCH_FF3, DCH_FF4, DCH_FF5, DCH_FF6,
  DCH_FX, DCH_HH24, DCH_HH12, DCH_HH,
  DCH_IDDD, DCH_ID, DCH_IW, DCH_IYYY,
  DCH_IYY, DCH_IY, DCH_I, DCH_J,
  DCH_MI, DCH_MM, DCH_MONTH, DCH_MON,
  DCH_MS, DCH_Month, DCH_Mon, DCH_OF,
  DCH_P_M, DCH_PM, DCH_Q, DCH_RM,
  DCH_SSSSS, DCH_SSSS, DCH_SS, DCH_TZH,
  DCH_TZM, DCH_TZ, DCH_US, DCH_WW,
  DCH_W, DCH_Y_YYY, DCH_YYYY, DCH_YYY,
  DCH_YY, DCH_Y, DCH_a_d, DCH_a_m,
  DCH_ad, DCH_am, DCH_b_c, DCH_bc,
  DCH_cc, DCH_day, DCH_ddd, DCH_dd,
  DCH_dy, DCH_d, DCH_ff1, DCH_ff2,
  DCH_ff3, DCH_ff4, DCH_ff5, DCH_ff6,
  DCH_fx, DCH_hh24, DCH_hh12, DCH_hh,
  DCH_iddd, DCH_id, DCH_iw, DCH_iyyy,
  DCH_iyy, DCH_iy, DCH_i, DCH_j,
  DCH_mi, DCH_mm, DCH_month, DCH_mon,
  DCH_ms, DCH_p_m, DCH_pm, DCH_q,
  DCH_rm, DCH_sssss, DCH_ssss, DCH_ss,
  DCH_tz, DCH_us, DCH_ww, DCH_w,
  DCH_y_yyy, DCH_yyyy, DCH_yyy, DCH_yy,
  DCH_y, _DCH_last_
}
 
enum  NUM_poz {
  NUM_COMMA, NUM_DEC, NUM_0, NUM_9,
  NUM_B, NUM_C, NUM_D, NUM_E,
  NUM_FM, NUM_G, NUM_L, NUM_MI,
  NUM_PL, NUM_PR, NUM_RN, NUM_SG,
  NUM_SP, NUM_S, NUM_TH, NUM_V,
  NUM_b, NUM_c, NUM_d, NUM_e,
  NUM_fm, NUM_g, NUM_l, NUM_mi,
  NUM_pl, NUM_pr, NUM_rn, NUM_sg,
  NUM_sp, NUM_s, NUM_th, NUM_v,
  _NUM_last_
}
 

Functions

static const KeyWordindex_seq_search (const char *str, const KeyWord *kw, const int *index)
 
static const KeySuffixsuff_search (const char *str, const KeySuffix *suf, int type)
 
static bool is_separator_char (const char *str)
 
static void NUMDesc_prepare (NUMDesc *num, FormatNode *n)
 
static void parse_format (FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num)
 
static void DCH_to_char (FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
 
static void DCH_from_char (FormatNode *node, const char *in, TmFromChar *out, Oid collid, bool std, bool *have_error)
 
static const char * get_th (char *num, int type)
 
static char * str_numth (char *dest, char *num, int type)
 
static int adjust_partial_year_to_2020 (int year)
 
static int strspace_len (const char *str)
 
static void from_char_set_mode (TmFromChar *tmfc, const FromCharDateMode mode, bool *have_error)
 
static void from_char_set_int (int *dest, const int value, const FormatNode *node, bool *have_error)
 
static int from_char_parse_int_len (int *dest, const char **src, const int len, FormatNode *node, bool *have_error)
 
static int from_char_parse_int (int *dest, const char **src, FormatNode *node, bool *have_error)
 
static int seq_search_ascii (const char *name, const char *const *array, int *len)
 
static int seq_search_localized (const char *name, char **array, int *len, Oid collid)
 
static int from_char_seq_search (int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, bool *have_error)
 
static void do_to_timestamp (text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, int *fprec, uint32 *flags, bool *have_error)
 
static char * fill_str (char *str, int c, int max)
 
static FormatNodeNUM_cache (int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
 
static char * int_to_roman (int number)
 
static void NUM_prepare_locale (NUMProc *Np)
 
static char * get_last_relevant_decnum (char *num)
 
static void NUM_numpart_from_char (NUMProc *Np, int id, int input_len)
 
static void NUM_numpart_to_char (NUMProc *Np, int id)
 
static char * NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number, int input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid)
 
static DCHCacheEntryDCH_cache_getnew (const char *str, bool std)
 
static DCHCacheEntryDCH_cache_search (const char *str, bool std)
 
static DCHCacheEntryDCH_cache_fetch (const char *str, bool std)
 
static NUMCacheEntryNUM_cache_getnew (const char *str)
 
static NUMCacheEntryNUM_cache_search (const char *str)
 
static NUMCacheEntryNUM_cache_fetch (const char *str)
 
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)
 
static char * str_tolower_z (const char *buff, Oid collid)
 
static char * str_toupper_z (const char *buff, Oid collid)
 
static char * str_initcap_z (const char *buff, Oid collid)
 
static char * asc_tolower_z (const char *buff)
 
static char * asc_toupper_z (const char *buff)
 
static bool is_next_separator (FormatNode *n)
 
static void DCH_prevent_counter_overflow (void)
 
static int DCH_datetime_type (FormatNode *node, bool *have_error)
 
static textdatetime_to_char_body (TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
 
Datum timestamp_to_char (PG_FUNCTION_ARGS)
 
Datum timestamptz_to_char (PG_FUNCTION_ARGS)
 
Datum interval_to_char (PG_FUNCTION_ARGS)
 
Datum to_timestamp (PG_FUNCTION_ARGS)
 
Datum to_date (PG_FUNCTION_ARGS)
 
Datum parse_datetime (text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, bool *have_error)
 
static void NUM_prevent_counter_overflow (void)
 
static void NUM_eat_non_data_chars (NUMProc *Np, int n, int input_len)
 
Datum numeric_to_number (PG_FUNCTION_ARGS)
 
Datum numeric_to_char (PG_FUNCTION_ARGS)
 
Datum int4_to_char (PG_FUNCTION_ARGS)
 
Datum int8_to_char (PG_FUNCTION_ARGS)
 
Datum float4_to_char (PG_FUNCTION_ARGS)
 
Datum float8_to_char (PG_FUNCTION_ARGS)
 

Variables

static const char *const months_full []
 
static const char *const days_short []
 
static const char *const adbc_strings [] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL}
 
static const char *const adbc_strings_long [] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL}
 
static const char *const ampm_strings [] = {am_STR, pm_STR, AM_STR, PM_STR, NULL}
 
static const char *const ampm_strings_long [] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL}
 
static const char *const rm_months_upper []
 
static const char *const rm_months_lower []
 
static const char *const rm1 [] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL}
 
static const char *const rm10 [] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL}
 
static const char *const rm100 [] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL}
 
static const char *const numTH [] = {"ST", "ND", "RD", "TH", NULL}
 
static const char *const numth [] = {"st", "nd", "rd", "th", NULL}
 
static DCHCacheEntryDCHCache [DCH_CACHE_ENTRIES]
 
static int n_DCHCache = 0
 
static int DCHCounter = 0
 
static NUMCacheEntryNUMCache [NUM_CACHE_ENTRIES]
 
static int n_NUMCache = 0
 
static int NUMCounter = 0
 
static const KeySuffix DCH_suff []
 
static const KeyWord DCH_keywords []
 
static const KeyWord NUM_keywords []
 
static const int DCH_index [KeyWord_INDEX_SIZE]
 
static const int NUM_index [KeyWord_INDEX_SIZE]
 

Macro Definition Documentation

◆ A_D_STR

#define A_D_STR   "A.D."

Definition at line 238 of file formatting.c.

Referenced by DCH_to_char().

◆ a_d_STR

#define a_d_STR   "a.d."

Definition at line 239 of file formatting.c.

Referenced by DCH_to_char().

◆ A_M_STR

#define A_M_STR   "A.M."

Definition at line 265 of file formatting.c.

Referenced by DCH_to_char().

◆ a_m_STR

#define a_m_STR   "a.m."

Definition at line 266 of file formatting.c.

Referenced by DCH_to_char().

◆ AD_STR

#define AD_STR   "AD"

Definition at line 240 of file formatting.c.

Referenced by DCH_to_char().

◆ ad_STR

#define ad_STR   "ad"

Definition at line 241 of file formatting.c.

Referenced by DCH_to_char().

◆ ADJUST_YEAR

#define ADJUST_YEAR (   year,
  is_interval 
)    ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))

Definition at line 236 of file formatting.c.

Referenced by DCH_to_char().

◆ AM_STR

#define AM_STR   "AM"

Definition at line 267 of file formatting.c.

Referenced by DCH_to_char().

◆ am_STR

#define am_STR   "am"

Definition at line 268 of file formatting.c.

Referenced by DCH_to_char().

◆ AMOUNT_TEST

#define AMOUNT_TEST (   s)    (Np->inout_p <= Np->inout + (input_len - (s)))

Definition at line 5152 of file formatting.c.

Referenced by NUM_numpart_from_char(), and NUM_processor().

◆ B_C_STR

#define B_C_STR   "B.C."

Definition at line 243 of file formatting.c.

Referenced by DCH_to_char().

◆ b_c_STR

#define b_c_STR   "b.c."

Definition at line 244 of file formatting.c.

Referenced by DCH_to_char().

◆ BC_STR

#define BC_STR   "BC"

Definition at line 245 of file formatting.c.

Referenced by DCH_to_char().

◆ bc_STR

#define bc_STR   "bc"

Definition at line 246 of file formatting.c.

Referenced by DCH_to_char().

◆ CHECK_ERROR

#define CHECK_ERROR
Value:
do { \
if (have_error && *have_error) \
goto on_error; \
} while (0)

Definition at line 131 of file formatting.c.

Referenced by DCH_from_char(), do_to_timestamp(), from_char_parse_int_len(), and parse_datetime().

◆ CLOCK_12_HOUR

#define CLOCK_12_HOUR   1

Definition at line 213 of file formatting.c.

Referenced by DCH_from_char(), and do_to_timestamp().

◆ CLOCK_24_HOUR

#define CLOCK_24_HOUR   0

Definition at line 212 of file formatting.c.

◆ DCH_CACHE_ENTRIES

#define DCH_CACHE_ENTRIES   20

Definition at line 407 of file formatting.c.

Referenced by DCH_cache_getnew().

◆ DCH_CACHE_OVERHEAD

#define DCH_CACHE_OVERHEAD   MAXALIGN(sizeof(bool) + sizeof(int))

Definition at line 397 of file formatting.c.

◆ DCH_CACHE_SIZE

#define DCH_CACHE_SIZE   ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)

Definition at line 402 of file formatting.c.

Referenced by datetime_to_char_body(), DCH_cache_getnew(), and do_to_timestamp().

◆ DCH_DATED

#define DCH_DATED   0x01

Definition at line 1022 of file formatting.c.

Referenced by DCH_datetime_type(), and parse_datetime().

◆ DCH_FLAG

#define DCH_FLAG   0x1 /* DATE-TIME flag */

◆ DCH_MAX_ITEM_SIZ

#define DCH_MAX_ITEM_SIZ   12 /* max localized day name */

Definition at line 156 of file formatting.c.

Referenced by datetime_to_char_body(), DCH_to_char(), and from_char_parse_int_len().

◆ DCH_S_FM

#define DCH_S_FM   0x01

Definition at line 544 of file formatting.c.

◆ DCH_S_SP

#define DCH_S_SP   0x08

Definition at line 547 of file formatting.c.

◆ DCH_S_TH

#define DCH_S_TH   0x02

Definition at line 545 of file formatting.c.

◆ DCH_S_th

#define DCH_S_th   0x04

Definition at line 546 of file formatting.c.

◆ DCH_S_TM

#define DCH_S_TM   0x10

Definition at line 548 of file formatting.c.

◆ DCH_TIMED

#define DCH_TIMED   0x02

Definition at line 1023 of file formatting.c.

Referenced by DCH_datetime_type(), and parse_datetime().

◆ DCH_to_char_fsec

#define DCH_to_char_fsec (   frac_fmt,
  frac_val 
)
Value:
sprintf(s, frac_fmt, (int) (frac_val)); \
if (S_THth(n->suffix)) \
str_numth(s, s, S_TH_TYPE(n->suffix)); \
s += strlen(s)
#define S_THth(_s)
Definition: formatting.c:554
#define sprintf
Definition: port.h:218
#define S_TH_TYPE(_s)
Definition: formatting.c:557

Referenced by DCH_to_char().

◆ DCH_ZONED

#define DCH_ZONED   0x04

Definition at line 1024 of file formatting.c.

Referenced by DCH_datetime_type(), and parse_datetime().

◆ DEBUG_TM

#define DEBUG_TM (   _X)

Definition at line 490 of file formatting.c.

Referenced by do_to_timestamp().

◆ DEBUG_TMFC

#define DEBUG_TMFC (   _X)

Definition at line 489 of file formatting.c.

Referenced by do_to_timestamp().

◆ INVALID_FOR_INTERVAL

#define INVALID_FOR_INTERVAL
Value:
do { \
if (is_interval) \
ereport(ERROR, \
(errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
errmsg("invalid format specification for an interval value"), \
errhint("Intervals are not tied to specific calendar dates."))); \
} while(0)
int errhint(const char *fmt,...)
Definition: elog.c:1156
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:909

Definition at line 527 of file formatting.c.

Referenced by DCH_to_char().

◆ IS_BLANK

#define IS_BLANK (   _f)    ((_f)->flag & NUM_F_BLANK)

Definition at line 369 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ IS_BRACKET

#define IS_BRACKET (   _f)    ((_f)->flag & NUM_F_BRACKET)

◆ IS_DECIMAL

#define IS_DECIMAL (   _f)    ((_f)->flag & NUM_F_DECIMAL)

◆ IS_EEEE

#define IS_EEEE (   _f)    ((_f)->flag & NUM_F_EEEE)

◆ IS_FILLMODE

#define IS_FILLMODE (   _f)    ((_f)->flag & NUM_F_FILLMODE)

Definition at line 370 of file formatting.c.

Referenced by NUM_numpart_to_char(), NUM_processor(), and NUMDesc_prepare().

◆ IS_LDECIMAL

#define IS_LDECIMAL (   _f)    ((_f)->flag & NUM_F_LDECIMAL)

Definition at line 367 of file formatting.c.

Referenced by NUM_prepare_locale().

◆ IS_LSIGN

#define IS_LSIGN (   _f)    ((_f)->flag & NUM_F_LSIGN)

◆ IS_MINUS

#define IS_MINUS (   _f)    ((_f)->flag & NUM_F_MINUS)

Definition at line 372 of file formatting.c.

Referenced by NUM_numpart_from_char(), NUM_processor(), and NUMDesc_prepare().

◆ IS_MULTI

#define IS_MULTI (   _f)    ((_f)->flag & NUM_F_MULTI)

◆ IS_PLUS

#define IS_PLUS (   _f)    ((_f)->flag & NUM_F_PLUS)

Definition at line 374 of file formatting.c.

Referenced by NUM_numpart_from_char(), NUM_processor(), and NUMDesc_prepare().

◆ IS_PREDEC_SPACE

#define IS_PREDEC_SPACE (   _n)
Value:
(IS_ZERO((_n)->Num)==false && \
(_n)->number == (_n)->number_p && \
*(_n)->number == '0' && \
(_n)->Num->post != 0)
#define IS_ZERO(_f)
Definition: formatting.c:368

Definition at line 5363 of file formatting.c.

Referenced by NUM_numpart_to_char().

◆ IS_ROMAN

#define IS_ROMAN (   _f)    ((_f)->flag & NUM_F_ROMAN)

◆ IS_ZERO

#define IS_ZERO (   _f)    ((_f)->flag & NUM_F_ZERO)

Definition at line 368 of file formatting.c.

Referenced by NUM_numpart_to_char(), NUM_processor(), and NUMDesc_prepare().

◆ KeyWord_INDEX_FILTER

#define KeyWord_INDEX_FILTER (   _c)    ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)

Definition at line 150 of file formatting.c.

Referenced by index_seq_search().

◆ KeyWord_INDEX_SIZE

#define KeyWord_INDEX_SIZE   ('~' - ' ')

Definition at line 149 of file formatting.c.

◆ NODE_TYPE_ACTION

#define NODE_TYPE_ACTION   2

◆ NODE_TYPE_CHAR

#define NODE_TYPE_CHAR   3

Definition at line 205 of file formatting.c.

Referenced by DCH_from_char(), and parse_format().

◆ NODE_TYPE_END

#define NODE_TYPE_END   1

◆ NODE_TYPE_SEPARATOR

#define NODE_TYPE_SEPARATOR   4

Definition at line 206 of file formatting.c.

Referenced by DCH_from_char(), and parse_format().

◆ NODE_TYPE_SPACE

#define NODE_TYPE_SPACE   5

Definition at line 207 of file formatting.c.

Referenced by DCH_from_char(), and parse_format().

◆ NUM_CACHE_ENTRIES

#define NUM_CACHE_ENTRIES   20

Definition at line 408 of file formatting.c.

Referenced by NUM_cache_getnew().

◆ NUM_CACHE_OVERHEAD

#define NUM_CACHE_OVERHEAD   MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))

Definition at line 399 of file formatting.c.

◆ NUM_CACHE_SIZE

#define NUM_CACHE_SIZE   ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)

Definition at line 404 of file formatting.c.

Referenced by NUM_cache(), and NUM_cache_getnew().

◆ NUM_F_BLANK

#define NUM_F_BLANK   (1 << 4)

Definition at line 346 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_BRACKET

#define NUM_F_BRACKET   (1 << 7)

Definition at line 349 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_DECIMAL

#define NUM_F_DECIMAL   (1 << 1)

Definition at line 343 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_EEEE

#define NUM_F_EEEE   (1 << 14)

Definition at line 356 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_FILLMODE

#define NUM_F_FILLMODE   (1 << 5)

Definition at line 347 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_LDECIMAL

#define NUM_F_LDECIMAL   (1 << 2)

Definition at line 344 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_LSIGN

#define NUM_F_LSIGN   (1 << 6)

Definition at line 348 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_MINUS

#define NUM_F_MINUS   (1 << 8)

Definition at line 350 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_MINUS_POST

#define NUM_F_MINUS_POST   (1 << 13)

Definition at line 355 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_MULTI

#define NUM_F_MULTI   (1 << 11)

Definition at line 353 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_PLUS

#define NUM_F_PLUS   (1 << 9)

Definition at line 351 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_PLUS_POST

#define NUM_F_PLUS_POST   (1 << 12)

Definition at line 354 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_ROMAN

#define NUM_F_ROMAN   (1 << 10)

Definition at line 352 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_ZERO

#define NUM_F_ZERO   (1 << 3)

Definition at line 345 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_FLAG

#define NUM_FLAG   0x2 /* NUMBER flag */

Definition at line 142 of file formatting.c.

Referenced by NUM_cache(), NUM_cache_fetch(), and parse_format().

◆ NUM_LSIGN_NONE

#define NUM_LSIGN_NONE   0

Definition at line 360 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_LSIGN_POST

#define NUM_LSIGN_POST   1

Definition at line 359 of file formatting.c.

Referenced by NUM_numpart_to_char(), NUM_processor(), and NUMDesc_prepare().

◆ NUM_LSIGN_PRE

#define NUM_LSIGN_PRE   (-1)

◆ NUM_MAX_ITEM_SIZ

#define NUM_MAX_ITEM_SIZ   8 /* roman number (RN has 15 chars) */

Definition at line 157 of file formatting.c.

Referenced by numeric_to_number().

◆ NUM_TOCHAR_finish

#define NUM_TOCHAR_finish
Value:
do { \
int len; \
NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \
\
if (shouldFree) \
pfree(format); \
\
/* \
* Convert null-terminated representation of result to standard text. \
* The result is usually much bigger than it needs to be, but there \
* seems little point in realloc'ing it smaller. \
*/ \
len = strlen(VARDATA(result)); \
SET_VARSIZE(result, len + VARHDRSZ); \
} while (0)
#define VARDATA(PTR)
Definition: postgres.h:315
#define VARHDRSZ
Definition: c.h:627
#define PG_GET_COLLATION()
Definition: fmgr.h:198
char sign
Definition: informix.c:668
static char format
static char * NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, int input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid)
Definition: formatting.c:5577

Definition at line 6071 of file formatting.c.

Referenced by float4_to_char(), float8_to_char(), int4_to_char(), int8_to_char(), and numeric_to_char().

◆ NUM_TOCHAR_prepare

#define NUM_TOCHAR_prepare
Value:
do { \
int len = VARSIZE_ANY_EXHDR(fmt); \
if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \
PG_RETURN_TEXT_P(cstring_to_text("")); \
result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
format = NUM_cache(len, &Num, fmt, &shouldFree); \
} while (0)
#define VARHDRSZ
Definition: c.h:627
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
Definition: formatting.c:4934
void * palloc0(Size size)
Definition: mcxt.c:1093
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define NUM_MAX_ITEM_SIZ
Definition: formatting.c:157
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
Definition: c.h:621

Definition at line 6058 of file formatting.c.

Referenced by float4_to_char(), float8_to_char(), int4_to_char(), int8_to_char(), and numeric_to_char().

◆ OVERLOAD_TEST

#define OVERLOAD_TEST   (Np->inout_p >= Np->inout + input_len)

Definition at line 5151 of file formatting.c.

Referenced by NUM_eat_non_data_chars(), NUM_numpart_from_char(), and NUM_processor().

◆ P_M_STR

#define P_M_STR   "P.M."

Definition at line 270 of file formatting.c.

Referenced by DCH_to_char().

◆ p_m_STR

#define p_m_STR   "p.m."

Definition at line 271 of file formatting.c.

Referenced by DCH_to_char().

◆ PM_STR

#define PM_STR   "PM"

Definition at line 272 of file formatting.c.

Referenced by DCH_to_char().

◆ pm_STR

#define pm_STR   "pm"

Definition at line 273 of file formatting.c.

Referenced by DCH_to_char().

◆ RETURN_ERROR

#define RETURN_ERROR (   throw_error)
Value:
do { \
if (have_error) \
{ \
*have_error = true; \
goto on_error; \
} \
else \
{ \
throw_error; \
} \
} while (0)

Definition at line 118 of file formatting.c.

Referenced by DCH_datetime_type(), DCH_from_char(), do_to_timestamp(), from_char_parse_int_len(), from_char_seq_search(), from_char_set_int(), from_char_set_mode(), and parse_datetime().

◆ S_FM

#define S_FM (   _s)    (((_s) & DCH_S_FM) ? 1 : 0)

Definition at line 560 of file formatting.c.

Referenced by DCH_to_char(), and from_char_parse_int_len().

◆ S_SP

#define S_SP (   _s)    (((_s) & DCH_S_SP) ? 1 : 0)

Definition at line 561 of file formatting.c.

◆ S_TH

#define S_TH (   _s)    (((_s) & DCH_S_TH) ? 1 : 0)

Definition at line 555 of file formatting.c.

◆ S_th

#define S_th (   _s)    (((_s) & DCH_S_th) ? 1 : 0)

Definition at line 556 of file formatting.c.

◆ S_TH_TYPE

#define S_TH_TYPE (   _s)    (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)

Definition at line 557 of file formatting.c.

Referenced by DCH_to_char().

◆ S_THth

#define S_THth (   _s)    ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)

Definition at line 554 of file formatting.c.

Referenced by DCH_to_char(), and is_next_separator().

◆ S_TM

#define S_TM (   _s)    (((_s) & DCH_S_TM) ? 1 : 0)

Definition at line 562 of file formatting.c.

Referenced by DCH_from_char(), and DCH_to_char().

◆ SKIP_THth

#define SKIP_THth (   ptr,
  _suf 
)
Value:
do { \
if (S_THth(_suf)) \
{ \
if (*(ptr)) (ptr) += pg_mblen(ptr); \
if (*(ptr)) (ptr) += pg_mblen(ptr); \
} \
} while (0)
#define S_THth(_s)
Definition: formatting.c:554
int pg_mblen(const char *mbstr)
Definition: mbutils.c:966

Definition at line 2150 of file formatting.c.

Referenced by DCH_from_char().

◆ STD_FLAG

#define STD_FLAG   0x4 /* STANDARD flag */

Definition at line 143 of file formatting.c.

Referenced by DCH_cache_fetch(), do_to_timestamp(), and parse_format().

◆ SUFFTYPE_POSTFIX

#define SUFFTYPE_POSTFIX   2

Definition at line 210 of file formatting.c.

Referenced by parse_format().

◆ SUFFTYPE_PREFIX

#define SUFFTYPE_PREFIX   1

Definition at line 209 of file formatting.c.

Referenced by parse_format().

◆ TH_LOWER

#define TH_LOWER   2

Definition at line 320 of file formatting.c.

Referenced by NUM_processor().

◆ TH_UPPER

#define TH_UPPER   1

Definition at line 319 of file formatting.c.

Referenced by get_th(), and NUM_processor().

◆ TM_SUFFIX_LEN

#define TM_SUFFIX_LEN   2

Definition at line 568 of file formatting.c.

Referenced by DCH_to_char().

◆ tmtcFsec

#define tmtcFsec (   _X)    ((_X)->fsec)

Definition at line 506 of file formatting.c.

Referenced by interval_to_char(), timestamp_to_char(), and timestamptz_to_char().

◆ tmtcTm

#define tmtcTm (   _X)    (&(_X)->tm)

Definition at line 504 of file formatting.c.

Referenced by interval_to_char(), timestamp_to_char(), and timestamptz_to_char().

◆ tmtcTzn

#define tmtcTzn (   _X)    ((_X)->tzn)

Definition at line 505 of file formatting.c.

Referenced by DCH_to_char(), and timestamptz_to_char().

◆ ZERO_tm

#define ZERO_tm (   _X)
Value:
do { \
(_X)->tm_sec = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \
(_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \
(_X)->tm_mday = (_X)->tm_mon = 1; \
(_X)->tm_zone = NULL; \
} while(0)

Definition at line 508 of file formatting.c.

Referenced by do_to_timestamp().

◆ ZERO_tmfc

#define ZERO_tmfc (   _X)    memset(_X, 0, sizeof(TmFromChar))

Definition at line 470 of file formatting.c.

Referenced by do_to_timestamp().

◆ ZERO_tmtc

#define ZERO_tmtc (   _X)
Value:
do { \
ZERO_tm( tmtcTm(_X) ); \
tmtcFsec(_X) = 0; \
tmtcTzn(_X) = NULL; \
} while(0)
#define tmtcTm(_X)
Definition: formatting.c:504

Definition at line 516 of file formatting.c.

Referenced by interval_to_char(), timestamp_to_char(), and timestamptz_to_char().

◆ zeroize_NUM

#define zeroize_NUM (   _n)
Value:
do { \
(_n)->flag = 0; \
(_n)->lsign = 0; \
(_n)->pre = 0; \
(_n)->post = 0; \
(_n)->pre_lsign_num = 0; \
(_n)->need_locale = 0; \
(_n)->multi = 0; \
(_n)->zero_start = 0; \
(_n)->zero_end = 0; \
} while(0)
char * flag(int b)
Definition: test-ctype.c:33

Definition at line 4799 of file formatting.c.

Referenced by NUM_cache(), and NUM_cache_fetch().

Typedef Documentation

◆ NUMProc

typedef struct NUMProc NUMProc

◆ TmToChar

typedef struct TmToChar TmToChar

Enumeration Type Documentation

◆ DCH_poz

enum DCH_poz
Enumerator
DCH_A_D 
DCH_A_M 
DCH_AD 
DCH_AM 
DCH_B_C 
DCH_BC 
DCH_CC 
DCH_DAY 
DCH_DDD 
DCH_DD 
DCH_DY 
DCH_Day 
DCH_Dy 
DCH_D 
DCH_FF1 
DCH_FF2 
DCH_FF3 
DCH_FF4 
DCH_FF5 
DCH_FF6 
DCH_FX 
DCH_HH24 
DCH_HH12 
DCH_HH 
DCH_IDDD 
DCH_ID 
DCH_IW 
DCH_IYYY 
DCH_IYY 
DCH_IY 
DCH_I 
DCH_J 
DCH_MI 
DCH_MM 
DCH_MONTH 
DCH_MON 
DCH_MS 
DCH_Month 
DCH_Mon 
DCH_OF 
DCH_P_M 
DCH_PM 
DCH_Q 
DCH_RM 
DCH_SSSSS 
DCH_SSSS 
DCH_SS 
DCH_TZH 
DCH_TZM 
DCH_TZ 
DCH_US 
DCH_WW 
DCH_W 
DCH_Y_YYY 
DCH_YYYY 
DCH_YYY 
DCH_YY 
DCH_Y 
DCH_a_d 
DCH_a_m 
DCH_ad 
DCH_am 
DCH_b_c 
DCH_bc 
DCH_cc 
DCH_day 
DCH_ddd 
DCH_dd 
DCH_dy 
DCH_d 
DCH_ff1 
DCH_ff2 
DCH_ff3 
DCH_ff4 
DCH_ff5 
DCH_ff6 
DCH_fx 
DCH_hh24 
DCH_hh12 
DCH_hh 
DCH_iddd 
DCH_id 
DCH_iw 
DCH_iyyy 
DCH_iyy 
DCH_iy 
DCH_i 
DCH_j 
DCH_mi 
DCH_mm 
DCH_month 
DCH_mon 
DCH_ms 
DCH_p_m 
DCH_pm 
DCH_q 
DCH_rm 
DCH_sssss 
DCH_ssss 
DCH_ss 
DCH_tz 
DCH_us 
DCH_ww 
DCH_w 
DCH_y_yyy 
DCH_yyyy 
DCH_yyy 
DCH_yy 
DCH_y 
_DCH_last_ 

Definition at line 611 of file formatting.c.

612 {
613  DCH_A_D,
614  DCH_A_M,
615  DCH_AD,
616  DCH_AM,
617  DCH_B_C,
618  DCH_BC,
619  DCH_CC,
620  DCH_DAY,
621  DCH_DDD,
622  DCH_DD,
623  DCH_DY,
624  DCH_Day,
625  DCH_Dy,
626  DCH_D,
627  DCH_FF1,
628  DCH_FF2,
629  DCH_FF3,
630  DCH_FF4,
631  DCH_FF5,
632  DCH_FF6,
633  DCH_FX, /* global suffix */
634  DCH_HH24,
635  DCH_HH12,
636  DCH_HH,
637  DCH_IDDD,
638  DCH_ID,
639  DCH_IW,
640  DCH_IYYY,
641  DCH_IYY,
642  DCH_IY,
643  DCH_I,
644  DCH_J,
645  DCH_MI,
646  DCH_MM,
647  DCH_MONTH,
648  DCH_MON,
649  DCH_MS,
650  DCH_Month,
651  DCH_Mon,
652  DCH_OF,
653  DCH_P_M,
654  DCH_PM,
655  DCH_Q,
656  DCH_RM,
657  DCH_SSSSS,
658  DCH_SSSS,
659  DCH_SS,
660  DCH_TZH,
661  DCH_TZM,
662  DCH_TZ,
663  DCH_US,
664  DCH_WW,
665  DCH_W,
666  DCH_Y_YYY,
667  DCH_YYYY,
668  DCH_YYY,
669  DCH_YY,
670  DCH_Y,
671  DCH_a_d,
672  DCH_a_m,
673  DCH_ad,
674  DCH_am,
675  DCH_b_c,
676  DCH_bc,
677  DCH_cc,
678  DCH_day,
679  DCH_ddd,
680  DCH_dd,
681  DCH_dy,
682  DCH_d,
683  DCH_ff1,
684  DCH_ff2,
685  DCH_ff3,
686  DCH_ff4,
687  DCH_ff5,
688  DCH_ff6,
689  DCH_fx,
690  DCH_hh24,
691  DCH_hh12,
692  DCH_hh,
693  DCH_iddd,
694  DCH_id,
695  DCH_iw,
696  DCH_iyyy,
697  DCH_iyy,
698  DCH_iy,
699  DCH_i,
700  DCH_j,
701  DCH_mi,
702  DCH_mm,
703  DCH_month,
704  DCH_mon,
705  DCH_ms,
706  DCH_p_m,
707  DCH_pm,
708  DCH_q,
709  DCH_rm,
710  DCH_sssss,
711  DCH_ssss,
712  DCH_ss,
713  DCH_tz,
714  DCH_us,
715  DCH_ww,
716  DCH_w,
717  DCH_y_yyy,
718  DCH_yyyy,
719  DCH_yyy,
720  DCH_yy,
721  DCH_y,
722 
723  /* last */
724  _DCH_last_
725 } DCH_poz;
DCH_poz
Definition: formatting.c:611

◆ FromCharDateMode

Enumerator
FROM_CHAR_DATE_NONE 
FROM_CHAR_DATE_GREGORIAN 
FROM_CHAR_DATE_ISOWEEK 

Definition at line 179 of file formatting.c.

180 {
181  FROM_CHAR_DATE_NONE = 0, /* Value does not affect date mode. */
182  FROM_CHAR_DATE_GREGORIAN, /* Gregorian (day, month, year) style date */
183  FROM_CHAR_DATE_ISOWEEK /* ISO 8601 week date */
FromCharDateMode
Definition: formatting.c:179

◆ NUM_poz

enum NUM_poz
Enumerator
NUM_COMMA 
NUM_DEC 
NUM_0 
NUM_9 
NUM_B 
NUM_C 
NUM_D 
NUM_E 
NUM_FM 
NUM_G 
NUM_L 
NUM_MI 
NUM_PL 
NUM_PR 
NUM_RN 
NUM_SG 
NUM_SP 
NUM_S 
NUM_TH 
NUM_V 
NUM_b 
NUM_c 
NUM_d 
NUM_e 
NUM_fm 
NUM_g 
NUM_l 
NUM_mi 
NUM_pl 
NUM_pr 
NUM_rn 
NUM_sg 
NUM_sp 
NUM_s 
NUM_th 
NUM_v 
_NUM_last_ 

Definition at line 727 of file formatting.c.

728 {
729  NUM_COMMA,
730  NUM_DEC,
731  NUM_0,
732  NUM_9,
733  NUM_B,
734  NUM_C,
735  NUM_D,
736  NUM_E,
737  NUM_FM,
738  NUM_G,
739  NUM_L,
740  NUM_MI,
741  NUM_PL,
742  NUM_PR,
743  NUM_RN,
744  NUM_SG,
745  NUM_SP,
746  NUM_S,
747  NUM_TH,
748  NUM_V,
749  NUM_b,
750  NUM_c,
751  NUM_d,
752  NUM_e,
753  NUM_fm,
754  NUM_g,
755  NUM_l,
756  NUM_mi,
757  NUM_pl,
758  NUM_pr,
759  NUM_rn,
760  NUM_sg,
761  NUM_sp,
762  NUM_s,
763  NUM_th,
764  NUM_v,
765 
766  /* last */
767  _NUM_last_
768 } NUM_poz;
NUM_poz
Definition: formatting.c:727

Function Documentation

◆ adjust_partial_year_to_2020()

static int adjust_partial_year_to_2020 ( int  year)
static

Definition at line 2231 of file formatting.c.

Referenced by DCH_from_char().

2232 {
2233  /*
2234  * Adjust all dates toward 2020; this is effectively what happens when we
2235  * assume '70' is 1970 and '69' is 2069.
2236  */
2237  /* Force 0-69 into the 2000's */
2238  if (year < 70)
2239  return year + 2000;
2240  /* Force 70-99 into the 1900's */
2241  else if (year < 100)
2242  return year + 1900;
2243  /* Force 100-519 into the 2000's */
2244  else if (year < 520)
2245  return year + 2000;
2246  /* Force 520-999 into the 1000's */
2247  else if (year < 1000)
2248  return year + 1000;
2249  else
2250  return year;
2251 }

◆ asc_initcap()

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

Definition at line 2081 of file formatting.c.

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

Referenced by str_initcap().

2082 {
2083  char *result;
2084  char *p;
2085  int wasalnum = false;
2086 
2087  if (!buff)
2088  return NULL;
2089 
2090  result = pnstrdup(buff, nbytes);
2091 
2092  for (p = result; *p; p++)
2093  {
2094  char c;
2095 
2096  if (wasalnum)
2097  *p = c = pg_ascii_tolower((unsigned char) *p);
2098  else
2099  *p = c = pg_ascii_toupper((unsigned char) *p);
2100  /* we don't trust isalnum() here */
2101  wasalnum = ((c >= 'A' && c <= 'Z') ||
2102  (c >= 'a' && c <= 'z') ||
2103  (c >= '0' && c <= '9'));
2104  }
2105 
2106  return result;
2107 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
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

◆ asc_tolower()

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

Definition at line 2035 of file formatting.c.

References pg_ascii_tolower(), and pnstrdup().

Referenced by asc_tolower_z(), get_collation_actual_version(), and str_tolower().

2036 {
2037  char *result;
2038  char *p;
2039 
2040  if (!buff)
2041  return NULL;
2042 
2043  result = pnstrdup(buff, nbytes);
2044 
2045  for (p = result; *p; p++)
2046  *p = pg_ascii_tolower((unsigned char) *p);
2047 
2048  return result;
2049 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
unsigned char pg_ascii_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:146

◆ asc_tolower_z()

static char* asc_tolower_z ( const char *  buff)
static

Definition at line 2130 of file formatting.c.

References asc_tolower().

Referenced by DCH_to_char(), and NUM_processor().

2131 {
2132  return asc_tolower(buff, strlen(buff));
2133 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2035

◆ asc_toupper()

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

Definition at line 2058 of file formatting.c.

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

2059 {
2060  char *result;
2061  char *p;
2062 
2063  if (!buff)
2064  return NULL;
2065 
2066  result = pnstrdup(buff, nbytes);
2067 
2068  for (p = result; *p; p++)
2069  *p = pg_ascii_toupper((unsigned char) *p);
2070 
2071  return result;
2072 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
unsigned char pg_ascii_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:135

◆ asc_toupper_z()

static char* asc_toupper_z ( const char *  buff)
static

Definition at line 2136 of file formatting.c.

References asc_toupper().

Referenced by DCH_to_char().

2137 {
2138  return asc_toupper(buff, strlen(buff));
2139 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2058

◆ datetime_to_char_body()

static text* datetime_to_char_body ( TmToChar tmtc,
text fmt,
bool  is_interval,
Oid  collid 
)
static

Definition at line 4022 of file formatting.c.

References cstring_to_text(), DCH_cache_fetch(), DCH_CACHE_SIZE, DCH_FLAG, DCH_index, DCH_MAX_ITEM_SIZ, DCH_to_char(), format, DCHCacheEntry::format, palloc(), parse_format(), pfree(), and text_to_cstring().

Referenced by interval_to_char(), timestamp_to_char(), and timestamptz_to_char().

4023 {
4024  FormatNode *format;
4025  char *fmt_str,
4026  *result;
4027  bool incache;
4028  int fmt_len;
4029  text *res;
4030 
4031  /*
4032  * Convert fmt to C string
4033  */
4034  fmt_str = text_to_cstring(fmt);
4035  fmt_len = strlen(fmt_str);
4036 
4037  /*
4038  * Allocate workspace for result as C string
4039  */
4040  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
4041  *result = '\0';
4042 
4043  if (fmt_len > DCH_CACHE_SIZE)
4044  {
4045  /*
4046  * Allocate new memory if format picture is bigger than static cache
4047  * and do not use cache (call parser always)
4048  */
4049  incache = false;
4050 
4051  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4052 
4053  parse_format(format, fmt_str, DCH_keywords,
4054  DCH_suff, DCH_index, DCH_FLAG, NULL);
4055  }
4056  else
4057  {
4058  /*
4059  * Use cache buffers
4060  */
4061  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
4062 
4063  incache = true;
4064  format = ent->format;
4065  }
4066 
4067  /* The real work is here */
4068  DCH_to_char(format, is_interval, tmtc, result, collid);
4069 
4070  if (!incache)
4071  pfree(format);
4072 
4073  pfree(fmt_str);
4074 
4075  /* convert C-string result to TEXT format */
4076  res = cstring_to_text(result);
4077 
4078  pfree(result);
4079  return res;
4080 }
static const KeySuffix DCH_suff[]
Definition: formatting.c:570
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:944
void pfree(void *pointer)
Definition: mcxt.c:1169
#define DCH_CACHE_SIZE
Definition: formatting.c:402
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
Definition: formatting.c:2654
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:412
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:1324
#define DCH_FLAG
Definition: formatting.c:141
text * cstring_to_text(const char *s)
Definition: varlena.c:190
char * text_to_cstring(const text *t)
Definition: varlena.c:223
void * palloc(Size size)
Definition: mcxt.c:1062
static const KeyWord DCH_keywords[]
Definition: formatting.c:774
Definition: c.h:621
static char format
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:156
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:3995

◆ DCH_cache_fetch()

static DCHCacheEntry * DCH_cache_fetch ( const char *  str,
bool  std 
)
static

Definition at line 3995 of file formatting.c.

References DCH_cache_getnew(), DCH_cache_search(), DCH_FLAG, DCH_index, DCHCacheEntry::format, parse_format(), STD_FLAG, and DCHCacheEntry::valid.

Referenced by datetime_to_char_body(), and do_to_timestamp().

3996 {
3997  DCHCacheEntry *ent;
3998 
3999  if ((ent = DCH_cache_search(str, std)) == NULL)
4000  {
4001  /*
4002  * Not in the cache, must run parser and save a new format-picture to
4003  * the cache. Do not mark the cache entry valid until parsing
4004  * succeeds.
4005  */
4006  ent = DCH_cache_getnew(str, std);
4007 
4009  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
4010 
4011  ent->valid = true;
4012  }
4013  return ent;
4014 }
static DCHCacheEntry * DCH_cache_getnew(const char *str, bool std)
Definition: formatting.c:3914
static const KeySuffix DCH_suff[]
Definition: formatting.c:570
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:944
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:412
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:1324
static DCHCacheEntry * DCH_cache_search(const char *str, bool std)
Definition: formatting.c:3974
#define DCH_FLAG
Definition: formatting.c:141
static const KeyWord DCH_keywords[]
Definition: formatting.c:774
#define STD_FLAG
Definition: formatting.c:143

◆ DCH_cache_getnew()

static DCHCacheEntry * DCH_cache_getnew ( const char *  str,
bool  std 
)
static

Definition at line 3914 of file formatting.c.

References DCHCacheEntry::age, Assert, DCH_CACHE_ENTRIES, DCH_CACHE_SIZE, DCH_prevent_counter_overflow(), DCHCounter, elog, i, MemoryContextAllocZero(), n_DCHCache, DCHCacheEntry::std, DCHCacheEntry::str, strlcpy(), TopMemoryContext, and DCHCacheEntry::valid.

Referenced by DCH_cache_fetch().

3915 {
3916  DCHCacheEntry *ent;
3917 
3918  /* Ensure we can advance DCHCounter below */
3920 
3921  /*
3922  * If cache is full, remove oldest entry (or recycle first not-valid one)
3923  */
3925  {
3926  DCHCacheEntry *old = DCHCache[0];
3927 
3928 #ifdef DEBUG_TO_FROM_CHAR
3929  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3930 #endif
3931  if (old->valid)
3932  {
3933  for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
3934  {
3935  ent = DCHCache[i];
3936  if (!ent->valid)
3937  {
3938  old = ent;
3939  break;
3940  }
3941  if (ent->age < old->age)
3942  old = ent;
3943  }
3944  }
3945 #ifdef DEBUG_TO_FROM_CHAR
3946  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3947 #endif
3948  old->valid = false;
3949  strlcpy(old->str, str, DCH_CACHE_SIZE + 1);
3950  old->age = (++DCHCounter);
3951  /* caller is expected to fill format, then set valid */
3952  return old;
3953  }
3954  else
3955  {
3956 #ifdef DEBUG_TO_FROM_CHAR
3957  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3958 #endif
3959  Assert(DCHCache[n_DCHCache] == NULL);
3960  DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
3962  ent->valid = false;
3963  strlcpy(ent->str, str, DCH_CACHE_SIZE + 1);
3964  ent->std = std;
3965  ent->age = (++DCHCounter);
3966  /* caller is expected to fill format, then set valid */
3967  ++n_DCHCache;
3968  return ent;
3969  }
3970 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:413
#define DCH_CACHE_SIZE
Definition: formatting.c:402
static int n_DCHCache
Definition: formatting.c:430
MemoryContext TopMemoryContext
Definition: mcxt.c:48
#define DCH_CACHE_ENTRIES
Definition: formatting.c:407
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:804
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3794
#define elog(elevel,...)
Definition: elog.h:232
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:429
static int DCHCounter
Definition: formatting.c:431

◆ DCH_cache_search()

static DCHCacheEntry * DCH_cache_search ( const char *  str,
bool  std 
)
static

Definition at line 3974 of file formatting.c.

References DCHCacheEntry::age, DCH_prevent_counter_overflow(), DCHCounter, i, n_DCHCache, DCHCacheEntry::std, DCHCacheEntry::str, and DCHCacheEntry::valid.

Referenced by DCH_cache_fetch().

3975 {
3976  /* Ensure we can advance DCHCounter below */
3978 
3979  for (int i = 0; i < n_DCHCache; i++)
3980  {
3981  DCHCacheEntry *ent = DCHCache[i];
3982 
3983  if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
3984  {
3985  ent->age = (++DCHCounter);
3986  return ent;
3987  }
3988  }
3989 
3990  return NULL;
3991 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:413
static int n_DCHCache
Definition: formatting.c:430
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3794
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:429
static int DCHCounter
Definition: formatting.c:431

◆ DCH_datetime_type()

static int DCH_datetime_type ( FormatNode node,
bool have_error 
)
static

Definition at line 3810 of file formatting.c.

References DCH_A_D, DCH_a_d, DCH_A_M, DCH_a_m, DCH_AD, DCH_ad, DCH_AM, DCH_am, DCH_B_C, DCH_b_c, DCH_BC, DCH_bc, DCH_CC, DCH_D, DCH_DATED, DCH_DAY, DCH_Day, DCH_day, DCH_DD, DCH_DDD, DCH_DY, DCH_Dy, DCH_dy, DCH_FF1, DCH_FF2, DCH_FF3, DCH_FF4, DCH_FF5, DCH_FF6, DCH_FX, DCH_HH, DCH_HH12, DCH_HH24, DCH_I, DCH_ID, DCH_IDDD, DCH_IY, DCH_IYY, DCH_IYYY, DCH_J, DCH_MI, DCH_MM, DCH_MON, DCH_Mon, DCH_mon, DCH_MONTH, DCH_Month, DCH_month, DCH_MS, DCH_OF, DCH_P_M, DCH_p_m, DCH_PM, DCH_pm, DCH_Q, DCH_RM, DCH_rm, DCH_SS, DCH_SSSS, DCH_TIMED, DCH_TZ, DCH_tz, DCH_TZH, DCH_TZM, DCH_US, DCH_W, DCH_WW, DCH_Y, DCH_Y_YYY, DCH_YY, DCH_YYY, DCH_YYYY, DCH_ZONED, ereport, errcode(), errmsg(), ERROR, KeyWord::id, FormatNode::key, KeyWord::name, NODE_TYPE_ACTION, NODE_TYPE_END, RETURN_ERROR, and FormatNode::type.

Referenced by do_to_timestamp().

3811 {
3812  FormatNode *n;
3813  int flags = 0;
3814 
3815  for (n = node; n->type != NODE_TYPE_END; n++)
3816  {
3817  if (n->type != NODE_TYPE_ACTION)
3818  continue;
3819 
3820  switch (n->key->id)
3821  {
3822  case DCH_FX:
3823  break;
3824  case DCH_A_M:
3825  case DCH_P_M:
3826  case DCH_a_m:
3827  case DCH_p_m:
3828  case DCH_AM:
3829  case DCH_PM:
3830  case DCH_am:
3831  case DCH_pm:
3832  case DCH_HH:
3833  case DCH_HH12:
3834  case DCH_HH24:
3835  case DCH_MI:
3836  case DCH_SS:
3837  case DCH_MS: /* millisecond */
3838  case DCH_US: /* microsecond */
3839  case DCH_FF1:
3840  case DCH_FF2:
3841  case DCH_FF3:
3842  case DCH_FF4:
3843  case DCH_FF5:
3844  case DCH_FF6:
3845  case DCH_SSSS:
3846  flags |= DCH_TIMED;
3847  break;
3848  case DCH_tz:
3849  case DCH_TZ:
3850  case DCH_OF:
3852  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3853  errmsg("formatting field \"%s\" is only supported in to_char",
3854  n->key->name))));
3855  flags |= DCH_ZONED;
3856  break;
3857  case DCH_TZH:
3858  case DCH_TZM:
3859  flags |= DCH_ZONED;
3860  break;
3861  case DCH_A_D:
3862  case DCH_B_C:
3863  case DCH_a_d:
3864  case DCH_b_c:
3865  case DCH_AD:
3866  case DCH_BC:
3867  case DCH_ad:
3868  case DCH_bc:
3869  case DCH_MONTH:
3870  case DCH_Month:
3871  case DCH_month:
3872  case DCH_MON:
3873  case DCH_Mon:
3874  case DCH_mon:
3875  case DCH_MM:
3876  case DCH_DAY:
3877  case DCH_Day:
3878  case DCH_day:
3879  case DCH_DY:
3880  case DCH_Dy:
3881  case DCH_dy:
3882  case DCH_DDD:
3883  case DCH_IDDD:
3884  case DCH_DD:
3885  case DCH_D:
3886  case DCH_ID:
3887  case DCH_WW:
3888  case DCH_Q:
3889  case DCH_CC:
3890  case DCH_Y_YYY:
3891  case DCH_YYYY:
3892  case DCH_IYYY:
3893  case DCH_YYY:
3894  case DCH_IYY:
3895  case DCH_YY:
3896  case DCH_IY:
3897  case DCH_Y:
3898  case DCH_I:
3899  case DCH_RM:
3900  case DCH_rm:
3901  case DCH_W:
3902  case DCH_J:
3903  flags |= DCH_DATED;
3904  break;
3905  }
3906  }
3907 
3908 on_error:
3909  return flags;
3910 }
#define NODE_TYPE_END
Definition: formatting.c:203
uint8 type
Definition: formatting.c:197
const KeyWord * key
Definition: formatting.c:200
int errcode(int sqlerrcode)
Definition: elog.c:698
int id
Definition: formatting.c:190
#define DCH_TIMED
Definition: formatting.c:1023
#define DCH_DATED
Definition: formatting.c:1022
#define NODE_TYPE_ACTION
Definition: formatting.c:204
#define ERROR
Definition: elog.h:46
#define DCH_ZONED
Definition: formatting.c:1024
const char * name
Definition: formatting.c:188
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define RETURN_ERROR(throw_error)
Definition: formatting.c:118

◆ DCH_from_char()

static void DCH_from_char ( FormatNode node,
const char *  in,
TmFromChar out,
Oid  collid,
bool  std,
bool have_error 
)
static

Definition at line 3296 of file formatting.c.

References adbc_strings, adbc_strings_long, adjust_partial_year_to_2020(), ampm_strings, ampm_strings_long, Assert, TmFromChar::bc, cache_locale_time(), TmFromChar::cc, FormatNode::character, CHECK_ERROR, TmFromChar::clock, CLOCK_12_HOUR, TmFromChar::d, KeyWord::date_mode, days, days_short, DCH_A_D, DCH_a_d, DCH_A_M, DCH_a_m, DCH_AD, DCH_ad, DCH_AM, DCH_am, DCH_B_C, DCH_b_c, DCH_BC, DCH_bc, DCH_CC, DCH_D, DCH_DAY, DCH_Day, DCH_day, DCH_DD, DCH_DDD, DCH_DY, DCH_Dy, DCH_dy, DCH_FF1, DCH_FF2, DCH_FF3, DCH_FF4, DCH_FF5, DCH_FF6, DCH_FX, DCH_HH, DCH_HH12, DCH_HH24, DCH_I, DCH_ID, DCH_IDDD, DCH_IW, DCH_IY, DCH_IYY, DCH_IYYY, DCH_J, DCH_MI, DCH_MM, DCH_MON, DCH_Mon, DCH_mon, DCH_MONTH, DCH_Month, DCH_month, DCH_MS, DCH_OF, DCH_P_M, DCH_p_m, DCH_PM, DCH_pm, DCH_Q, DCH_RM, DCH_rm, DCH_SS, DCH_SSSS, DCH_TZ, DCH_tz, DCH_TZH, DCH_TZM, DCH_US, DCH_W, DCH_WW, DCH_Y, DCH_Y_YYY, DCH_YY, DCH_YYY, DCH_YYYY, TmFromChar::dd, TmFromChar::ddd, ereport, errcode(), errmsg(), ERROR, TmFromChar::ff, from_char_parse_int(), from_char_parse_int_len(), from_char_seq_search(), from_char_set_int(), from_char_set_mode(), TmFromChar::hh, KeyWord::id, InvalidOid, is_separator_char(), TmFromChar::j, FormatNode::key, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, TmFromChar::mi, TmFromChar::mm, months, months_full, MONTHS_PER_YEAR, TmFromChar::ms, KeyWord::name, NODE_TYPE_ACTION, NODE_TYPE_CHAR, NODE_TYPE_END, NODE_TYPE_SEPARATOR, NODE_TYPE_SPACE, pg_mblen(), TmFromChar::pm, RETURN_ERROR, rm_months_lower, S_TM, SKIP_THth, TmFromChar::ss, TmFromChar::ssss, FormatNode::suffix, FormatNode::type, TmFromChar::tzh, TmFromChar::tzm, TmFromChar::tzsign, TmFromChar::us, value, TmFromChar::w, TmFromChar::ww, TmFromChar::year, and TmFromChar::yysz.

Referenced by do_to_timestamp().

3298 {
3299  FormatNode *n;
3300  const char *s;
3301  int len,
3302  value;
3303  bool fx_mode = std;
3304 
3305  /* number of extra skipped characters (more than given in format string) */
3306  int extra_skip = 0;
3307 
3308  /* cache localized days and months */
3310 
3311  for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
3312  {
3313  /*
3314  * Ignore spaces at the beginning of the string and before fields when
3315  * not in FX (fixed width) mode.
3316  */
3317  if (!fx_mode && (n->type != NODE_TYPE_ACTION || n->key->id != DCH_FX) &&
3318  (n->type == NODE_TYPE_ACTION || n == node))
3319  {
3320  while (*s != '\0' && isspace((unsigned char) *s))
3321  {
3322  s++;
3323  extra_skip++;
3324  }
3325  }
3326 
3327  if (n->type == NODE_TYPE_SPACE || n->type == NODE_TYPE_SEPARATOR)
3328  {
3329  if (std)
3330  {
3331  /*
3332  * Standard mode requires strict matching between format
3333  * string separators/spaces and input string.
3334  */
3335  Assert(n->character[0] && !n->character[1]);
3336 
3337  if (*s == n->character[0])
3338  s++;
3339  else
3341  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3342  errmsg("unmatched format separator \"%c\"",
3343  n->character[0]))));
3344  }
3345  else if (!fx_mode)
3346  {
3347  /*
3348  * In non FX (fixed format) mode one format string space or
3349  * separator match to one space or separator in input string.
3350  * Or match nothing if there is no space or separator in the
3351  * current position of input string.
3352  */
3353  extra_skip--;
3354  if (isspace((unsigned char) *s) || is_separator_char(s))
3355  {
3356  s++;
3357  extra_skip++;
3358  }
3359  }
3360  else
3361  {
3362  /*
3363  * In FX mode, on format string space or separator we consume
3364  * exactly one character from input string. Notice we don't
3365  * insist that the consumed character match the format's
3366  * character.
3367  */
3368  s += pg_mblen(s);
3369  }
3370  continue;
3371  }
3372  else if (n->type != NODE_TYPE_ACTION)
3373  {
3374  /*
3375  * Text character, so consume one character from input string.
3376  * Notice we don't insist that the consumed character match the
3377  * format's character.
3378  */
3379  if (!fx_mode)
3380  {
3381  /*
3382  * In non FX mode we might have skipped some extra characters
3383  * (more than specified in format string) before. In this
3384  * case we don't skip input string character, because it might
3385  * be part of field.
3386  */
3387  if (extra_skip > 0)
3388  extra_skip--;
3389  else
3390  s += pg_mblen(s);
3391  }
3392  else
3393  {
3394  int chlen = pg_mblen(s);
3395 
3396  /*
3397  * Standard mode requires strict match of format characters.
3398  */
3399  if (std && n->type == NODE_TYPE_CHAR &&
3400  strncmp(s, n->character, chlen) != 0)
3402  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3403  errmsg("unmatched format character \"%s\"",
3404  n->character))));
3405 
3406  s += chlen;
3407  }
3408  continue;
3409  }
3410 
3411  from_char_set_mode(out, n->key->date_mode, have_error);
3412  CHECK_ERROR;
3413 
3414  switch (n->key->id)
3415  {
3416  case DCH_FX:
3417  fx_mode = true;
3418  break;
3419  case DCH_A_M:
3420  case DCH_P_M:
3421  case DCH_a_m:
3422  case DCH_p_m:
3424  NULL, InvalidOid,
3425  n, have_error);
3426  CHECK_ERROR;
3427  from_char_set_int(&out->pm, value % 2, n, have_error);
3428  CHECK_ERROR;
3429  out->clock = CLOCK_12_HOUR;
3430  break;
3431  case DCH_AM:
3432  case DCH_PM:
3433  case DCH_am:
3434  case DCH_pm:
3435  from_char_seq_search(&value, &s, ampm_strings,
3436  NULL, InvalidOid,
3437  n, have_error);
3438  CHECK_ERROR;
3439  from_char_set_int(&out->pm, value % 2, n, have_error);
3440  CHECK_ERROR;
3441  out->clock = CLOCK_12_HOUR;
3442  break;
3443  case DCH_HH:
3444  case DCH_HH12:
3445  from_char_parse_int_len(&out->hh, &s, 2, n, have_error);
3446  CHECK_ERROR;
3447  out->clock = CLOCK_12_HOUR;
3448  SKIP_THth(s, n->suffix);
3449  break;
3450  case DCH_HH24:
3451  from_char_parse_int_len(&out->hh, &s, 2, n, have_error);
3452  CHECK_ERROR;
3453  SKIP_THth(s, n->suffix);
3454  break;
3455  case DCH_MI:
3456  from_char_parse_int(&out->mi, &s, n, have_error);
3457  CHECK_ERROR;
3458  SKIP_THth(s, n->suffix);
3459  break;
3460  case DCH_SS:
3461  from_char_parse_int(&out->ss, &s, n, have_error);
3462  CHECK_ERROR;
3463  SKIP_THth(s, n->suffix);
3464  break;
3465  case DCH_MS: /* millisecond */
3466  len = from_char_parse_int_len(&out->ms, &s, 3, n, have_error);
3467  CHECK_ERROR;
3468 
3469  /*
3470  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
3471  */
3472  out->ms *= len == 1 ? 100 :
3473  len == 2 ? 10 : 1;
3474 
3475  SKIP_THth(s, n->suffix);
3476  break;
3477  case DCH_FF1:
3478  case DCH_FF2:
3479  case DCH_FF3:
3480  case DCH_FF4:
3481  case DCH_FF5:
3482  case DCH_FF6:
3483  out->ff = n->key->id - DCH_FF1 + 1;
3484  /* fall through */
3485  case DCH_US: /* microsecond */
3486  len = from_char_parse_int_len(&out->us, &s,
3487  n->key->id == DCH_US ? 6 :
3488  out->ff, n, have_error);
3489  CHECK_ERROR;
3490 
3491  out->us *= len == 1 ? 100000 :
3492  len == 2 ? 10000 :
3493  len == 3 ? 1000 :
3494  len == 4 ? 100 :
3495  len == 5 ? 10 : 1;
3496 
3497  SKIP_THth(s, n->suffix);
3498  break;
3499  case DCH_SSSS:
3500  from_char_parse_int(&out->ssss, &s, n, have_error);
3501  CHECK_ERROR;
3502  SKIP_THth(s, n->suffix);
3503  break;
3504  case DCH_tz:
3505  case DCH_TZ:
3506  case DCH_OF:
3508  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3509  errmsg("formatting field \"%s\" is only supported in to_char",
3510  n->key->name))));
3511  CHECK_ERROR;
3512  break;
3513  case DCH_TZH:
3514 
3515  /*
3516  * Value of TZH might be negative. And the issue is that we
3517  * might swallow minus sign as the separator. So, if we have
3518  * skipped more characters than specified in the format
3519  * string, then we consider prepending last skipped minus to
3520  * TZH.
3521  */
3522  if (*s == '+' || *s == '-' || *s == ' ')
3523  {
3524  out->tzsign = *s == '-' ? -1 : +1;
3525  s++;
3526  }
3527  else
3528  {
3529  if (extra_skip > 0 && *(s - 1) == '-')
3530  out->tzsign = -1;
3531  else
3532  out->tzsign = +1;
3533  }
3534 
3535  from_char_parse_int_len(&out->tzh, &s, 2, n, have_error);
3536  CHECK_ERROR;
3537  break;
3538  case DCH_TZM:
3539  /* assign positive timezone sign if TZH was not seen before */
3540  if (!out->tzsign)
3541  out->tzsign = +1;
3542  from_char_parse_int_len(&out->tzm, &s, 2, n, have_error);
3543  CHECK_ERROR;
3544  break;
3545  case DCH_A_D:
3546  case DCH_B_C:
3547  case DCH_a_d:
3548  case DCH_b_c:
3550  NULL, InvalidOid,
3551  n, have_error);
3552  CHECK_ERROR;
3553  from_char_set_int(&out->bc, value % 2, n, have_error);
3554  CHECK_ERROR;
3555  break;
3556  case DCH_AD:
3557  case DCH_BC:
3558  case DCH_ad:
3559  case DCH_bc:
3560  from_char_seq_search(&value, &s, adbc_strings,
3561  NULL, InvalidOid,
3562  n, have_error);
3563  CHECK_ERROR;
3564  from_char_set_int(&out->bc, value % 2, n, have_error);
3565  CHECK_ERROR;
3566  break;
3567  case DCH_MONTH:
3568  case DCH_Month:
3569  case DCH_month:
3570  from_char_seq_search(&value, &s, months_full,
3571  S_TM(n->suffix) ? localized_full_months : NULL,
3572  collid,
3573  n, have_error);
3574  CHECK_ERROR;
3575  from_char_set_int(&out->mm, value + 1, n, have_error);
3576  CHECK_ERROR;
3577  break;
3578  case DCH_MON:
3579  case DCH_Mon:
3580  case DCH_mon:
3581  from_char_seq_search(&value, &s, months,
3582  S_TM(n->suffix) ? localized_abbrev_months : NULL,
3583  collid,
3584  n, have_error);
3585  CHECK_ERROR;
3586  from_char_set_int(&out->mm, value + 1, n, have_error);
3587  CHECK_ERROR;
3588  break;
3589  case DCH_MM:
3590  from_char_parse_int(&out->mm, &s, n, have_error);
3591  CHECK_ERROR;
3592  SKIP_THth(s, n->suffix);
3593  break;
3594  case DCH_DAY:
3595  case DCH_Day:
3596  case DCH_day:
3597  from_char_seq_search(&value, &s, days,
3598  S_TM(n->suffix) ? localized_full_days : NULL,
3599  collid,
3600  n, have_error);
3601  CHECK_ERROR;
3602  from_char_set_int(&out->d, value, n, have_error);
3603  CHECK_ERROR;
3604  out->d++;
3605  break;
3606  case DCH_DY:
3607  case DCH_Dy:
3608  case DCH_dy:
3609  from_char_seq_search(&value, &s, days_short,
3610  S_TM(n->suffix) ? localized_abbrev_days : NULL,
3611  collid,
3612  n, have_error);
3613  CHECK_ERROR;
3614  from_char_set_int(&out->d, value, n, have_error);
3615  CHECK_ERROR;
3616  out->d++;
3617  break;
3618  case DCH_DDD:
3619  from_char_parse_int(&out->ddd, &s, n, have_error);
3620  CHECK_ERROR;
3621  SKIP_THth(s, n->suffix);
3622  break;
3623  case DCH_IDDD:
3624  from_char_parse_int_len(&out->ddd, &s, 3, n, have_error);
3625  CHECK_ERROR;
3626  SKIP_THth(s, n->suffix);
3627  break;
3628  case DCH_DD:
3629  from_char_parse_int(&out->dd, &s, n, have_error);
3630  CHECK_ERROR;
3631  SKIP_THth(s, n->suffix);
3632  break;
3633  case DCH_D:
3634  from_char_parse_int(&out->d, &s, n, have_error);
3635  CHECK_ERROR;
3636  SKIP_THth(s, n->suffix);
3637  break;
3638  case DCH_ID:
3639  from_char_parse_int_len(&out->d, &s, 1, n, have_error);
3640  CHECK_ERROR;
3641  /* Shift numbering to match Gregorian where Sunday = 1 */
3642  if (++out->d > 7)
3643  out->d = 1;
3644  SKIP_THth(s, n->suffix);
3645  break;
3646  case DCH_WW:
3647  case DCH_IW:
3648  from_char_parse_int(&out->ww, &s, n, have_error);
3649  CHECK_ERROR;
3650  SKIP_THth(s, n->suffix);
3651  break;
3652  case DCH_Q:
3653 
3654  /*
3655  * We ignore 'Q' when converting to date because it is unclear
3656  * which date in the quarter to use, and some people specify
3657  * both quarter and month, so if it was honored it might
3658  * conflict with the supplied month. That is also why we don't
3659  * throw an error.
3660  *
3661  * We still parse the source string for an integer, but it
3662  * isn't stored anywhere in 'out'.
3663  */
3664  from_char_parse_int((int *) NULL, &s, n, have_error);
3665  CHECK_ERROR;
3666  SKIP_THth(s, n->suffix);
3667  break;
3668  case DCH_CC:
3669  from_char_parse_int(&out->cc, &s, n, have_error);
3670  CHECK_ERROR;
3671  SKIP_THth(s, n->suffix);
3672  break;
3673  case DCH_Y_YYY:
3674  {
3675  int matched,
3676  years,
3677  millennia,
3678  nch;
3679 
3680  matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3681  if (matched < 2)
3683  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3684  errmsg("invalid input string for \"Y,YYY\""))));
3685  years += (millennia * 1000);
3686  from_char_set_int(&out->year, years, n, have_error);
3687  CHECK_ERROR;
3688  out->yysz = 4;
3689  s += nch;
3690  SKIP_THth(s, n->suffix);
3691  }
3692  break;
3693  case DCH_YYYY:
3694  case DCH_IYYY:
3695  from_char_parse_int(&out->year, &s, n, have_error);
3696  CHECK_ERROR;
3697  out->yysz = 4;
3698  SKIP_THth(s, n->suffix);
3699  break;
3700  case DCH_YYY:
3701  case DCH_IYY:
3702  len = from_char_parse_int(&out->year, &s, n, have_error);
3703  CHECK_ERROR;
3704  if (len < 4)
3705  out->year = adjust_partial_year_to_2020(out->year);
3706  out->yysz = 3;
3707  SKIP_THth(s, n->suffix);
3708  break;
3709  case DCH_YY:
3710  case DCH_IY:
3711  len = from_char_parse_int(&out->year, &s, n, have_error);
3712  CHECK_ERROR;
3713  if (len < 4)
3714  out->year = adjust_partial_year_to_2020(out->year);
3715  out->yysz = 2;
3716  SKIP_THth(s, n->suffix);
3717  break;
3718  case DCH_Y:
3719  case DCH_I:
3720  len = from_char_parse_int(&out->year, &s, n, have_error);
3721  CHECK_ERROR;
3722  if (len < 4)
3723  out->year = adjust_partial_year_to_2020(out->year);
3724  out->yysz = 1;
3725  SKIP_THth(s, n->suffix);
3726  break;
3727  case DCH_RM:
3728  case DCH_rm:
3730  NULL, InvalidOid,
3731  n, have_error);
3732  CHECK_ERROR;
3733  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value,
3734  n, have_error);
3735  CHECK_ERROR;
3736  break;
3737  case DCH_W:
3738  from_char_parse_int(&out->w, &s, n, have_error);
3739  CHECK_ERROR;
3740  SKIP_THth(s, n->suffix);
3741  break;
3742  case DCH_J:
3743  from_char_parse_int(&out->j, &s, n, have_error);
3744  CHECK_ERROR;
3745  SKIP_THth(s, n->suffix);
3746  break;
3747  }
3748 
3749  /* Ignore all spaces after fields */
3750  if (!fx_mode)
3751  {
3752  extra_skip = 0;
3753  while (*s != '\0' && isspace((unsigned char) *s))
3754  {
3755  s++;
3756  extra_skip++;
3757  }
3758  }
3759  }
3760 
3761  /*
3762  * Standard parsing mode doesn't allow unmatched format patterns or
3763  * trailing characters in the input string.
3764  */
3765  if (std)
3766  {
3767  if (n->type != NODE_TYPE_END)
3769  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3770  errmsg("input string is too short for datetime format"))));
3771 
3772  while (*s != '\0' && isspace((unsigned char) *s))
3773  s++;
3774 
3775  if (*s != '\0')
3777  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3778  errmsg("trailing characters remain in input string "
3779  "after datetime format"))));
3780  }
3781 
3782 on_error:
3783  return;
3784 }
#define NODE_TYPE_END
Definition: formatting.c:203
uint8 type
Definition: formatting.c:197
const KeyWord * key
Definition: formatting.c:200
static const char *const adbc_strings_long[]
Definition: formatting.c:259
FromCharDateMode date_mode
Definition: formatting.c:192
int errcode(int sqlerrcode)
Definition: elog.c:698
static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode, bool *have_error)
Definition: formatting.c:2276
int id
Definition: formatting.c:190
static const char *const ampm_strings_long[]
Definition: formatting.c:286
#define CHECK_ERROR
Definition: formatting.c:131
static int from_char_seq_search(int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, bool *have_error)
Definition: formatting.c:2605
static const char *const adbc_strings[]
Definition: formatting.c:258
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
const char *const months[]
Definition: datetime.c:65
#define NODE_TYPE_ACTION
Definition: formatting.c:204
#define ERROR
Definition: elog.h:46
char character[MAX_MULTIBYTE_CHAR_LEN+1]
Definition: formatting.c:198
#define SKIP_THth(ptr, _suf)
Definition: formatting.c:2150
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:99
static bool is_separator_char(const char *str)
Definition: formatting.c:1135
#define NODE_TYPE_SPACE
Definition: formatting.c:207
const char *const days[]
Definition: datetime.c:68
#define NODE_TYPE_SEPARATOR
Definition: formatting.c:206
char * localized_full_days[7+1]
Definition: pg_locale.c:98
#define CLOCK_12_HOUR
Definition: formatting.c:213
static const char *const ampm_strings[]
Definition: formatting.c:285
const char * name
Definition: formatting.c:188
static const char *const months_full[]
Definition: formatting.c:220
#define InvalidOid
Definition: postgres_ext.h:36
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:157
char * localized_full_months[12+1]
Definition: pg_locale.c:100
static int adjust_partial_year_to_2020(int year)
Definition: formatting.c:2231
#define Assert(condition)
Definition: c.h:804
void cache_locale_time(void)
Definition: pg_locale.c:747
int pg_mblen(const char *mbstr)
Definition: mbutils.c:966
#define NODE_TYPE_CHAR
Definition: formatting.c:205
uint8 suffix
Definition: formatting.c:199
static int from_char_parse_int(int *dest, const char **src, FormatNode *node, bool *have_error)
Definition: formatting.c:2447
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define S_TM(_s)
Definition: formatting.c:562
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:97
static void from_char_set_int(int *dest, const int value, const FormatNode *node, bool *have_error)
Definition: formatting.c:2303
static const char *const rm_months_lower[]
Definition: formatting.c:297
#define RETURN_ERROR(throw_error)
Definition: formatting.c:118
static int from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node, bool *have_error)
Definition: formatting.c:2344
static const char *const days_short[]
Definition: formatting.c:225

◆ DCH_prevent_counter_overflow()

static void DCH_prevent_counter_overflow ( void  )
inlinestatic

Definition at line 3794 of file formatting.c.

References DCHCounter, i, and n_DCHCache.

Referenced by DCH_cache_getnew(), and DCH_cache_search().

3795 {
3796  if (DCHCounter >= (INT_MAX - 1))
3797  {
3798  for (int i = 0; i < n_DCHCache; i++)
3799  DCHCache[i]->age >>= 1;
3800  DCHCounter >>= 1;
3801  }
3802 }
static int n_DCHCache
Definition: formatting.c:430
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:429
static int DCHCounter
Definition: formatting.c:431

◆ DCH_to_char()

static void DCH_to_char ( FormatNode node,
bool  is_interval,
TmToChar in,
char *  out,
Oid  collid 
)
static

Definition at line 2654 of file formatting.c.

References A_D_STR, a_d_STR, A_M_STR, a_m_STR, AD_STR, ad_STR, ADJUST_YEAR, AM_STR, am_STR, asc_tolower_z(), asc_toupper_z(), B_C_STR, b_c_STR, BC_STR, bc_STR, cache_locale_time(), FormatNode::character, date2isoweek(), date2isoyear(), date2isoyearday(), date2j(), days, days_short, DCH_A_D, DCH_a_d, DCH_A_M, DCH_a_m, DCH_AD, DCH_ad, DCH_AM, DCH_am, DCH_B_C, DCH_b_c, DCH_BC, DCH_bc, DCH_CC, DCH_D, DCH_DAY, DCH_Day, DCH_day, DCH_DD, DCH_DDD, DCH_DY, DCH_Dy, DCH_dy, DCH_FF1, DCH_FF2, DCH_FF3, DCH_FF4, DCH_FF5, DCH_FF6, DCH_HH, DCH_HH12, DCH_HH24, DCH_I, DCH_ID, DCH_IDDD, DCH_IW, DCH_IY, DCH_IYY, DCH_IYYY, DCH_J, DCH_MAX_ITEM_SIZ, DCH_MI, DCH_MM, DCH_MON, DCH_Mon, DCH_mon, DCH_MONTH, DCH_Month, DCH_month, DCH_MS, DCH_OF, DCH_P_M, DCH_p_m, DCH_PM, DCH_pm, DCH_Q, DCH_RM, DCH_rm, DCH_SS, DCH_SSSS, DCH_to_char_fsec, DCH_TZ, DCH_tz, DCH_TZH, DCH_TZM, DCH_US, DCH_W, DCH_WW, DCH_Y, DCH_Y_YYY, DCH_YY, DCH_YYY, DCH_YYYY, ereport, errcode(), errmsg(), ERROR, TmToChar::fsec, HOURS_PER_DAY, i, KeyWord::id, INVALID_FOR_INTERVAL, FormatNode::key, KeyWord::len, localized_abbrev_days, localized_abbrev_months, localized_full_days, localized_full_months, months, months_full, MONTHS_PER_YEAR, NODE_TYPE_ACTION, NODE_TYPE_END, P_M_STR, p_m_STR, pfree(), PM_STR, pm_STR, rm_months_lower, rm_months_upper, S_FM, S_TH_TYPE, S_THth, S_TM, SECS_PER_HOUR, SECS_PER_MINUTE, sprintf, generate_unaccent_rules::str, str_initcap_z(), str_numth(), str_tolower_z(), str_toupper_z(), FormatNode::suffix, TmToChar::tm, pg_tm::tm_gmtoff, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, TM_SUFFIX_LEN, pg_tm::tm_wday, pg_tm::tm_yday, pg_tm::tm_year, tmtcTzn, and FormatNode::type.

Referenced by datetime_to_char_body().

2655 {
2656  FormatNode *n;
2657  char *s;
2658  struct pg_tm *tm = &in->tm;
2659  int i;
2660 
2661  /* cache localized days and months */
2663 
2664  s = out;
2665  for (n = node; n->type != NODE_TYPE_END; n++)
2666  {
2667  if (n->type != NODE_TYPE_ACTION)
2668  {
2669  strcpy(s, n->character);
2670  s += strlen(s);
2671  continue;
2672  }
2673 
2674  switch (n->key->id)
2675  {
2676  case DCH_A_M:
2677  case DCH_P_M:
2678  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2679  ? P_M_STR : A_M_STR);
2680  s += strlen(s);
2681  break;
2682  case DCH_AM:
2683  case DCH_PM:
2684  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2685  ? PM_STR : AM_STR);
2686  s += strlen(s);
2687  break;
2688  case DCH_a_m:
2689  case DCH_p_m:
2690  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2691  ? p_m_STR : a_m_STR);
2692  s += strlen(s);
2693  break;
2694  case DCH_am:
2695  case DCH_pm:
2696  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2697  ? pm_STR : am_STR);
2698  s += strlen(s);
2699  break;
2700  case DCH_HH:
2701  case DCH_HH12:
2702 
2703  /*
2704  * display time as shown on a 12-hour clock, even for
2705  * intervals
2706  */
2707  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2708  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? HOURS_PER_DAY / 2 :
2709  tm->tm_hour % (HOURS_PER_DAY / 2));
2710  if (S_THth(n->suffix))
2711  str_numth(s, s, S_TH_TYPE(n->suffix));
2712  s += strlen(s);
2713  break;
2714  case DCH_HH24:
2715  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2716  tm->tm_hour);
2717  if (S_THth(n->suffix))
2718  str_numth(s, s, S_TH_TYPE(n->suffix));
2719  s += strlen(s);
2720  break;
2721  case DCH_MI:
2722  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2723  tm->tm_min);
2724  if (S_THth(n->suffix))
2725  str_numth(s, s, S_TH_TYPE(n->suffix));
2726  s += strlen(s);
2727  break;
2728  case DCH_SS:
2729  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2730  tm->tm_sec);
2731  if (S_THth(n->suffix))
2732  str_numth(s, s, S_TH_TYPE(n->suffix));
2733  s += strlen(s);
2734  break;
2735 
2736 #define DCH_to_char_fsec(frac_fmt, frac_val) \
2737  sprintf(s, frac_fmt, (int) (frac_val)); \
2738  if (S_THth(n->suffix)) \
2739  str_numth(s, s, S_TH_TYPE(n->suffix)); \
2740  s += strlen(s)
2741 
2742  case DCH_FF1: /* tenth of second */
2743  DCH_to_char_fsec("%01d", in->fsec / 100000);
2744  break;
2745  case DCH_FF2: /* hundredth of second */
2746  DCH_to_char_fsec("%02d", in->fsec / 10000);
2747  break;
2748  case DCH_FF3:
2749  case DCH_MS: /* millisecond */
2750  DCH_to_char_fsec("%03d", in->fsec / 1000);
2751  break;
2752  case DCH_FF4: /* tenth of a millisecond */
2753  DCH_to_char_fsec("%04d", in->fsec / 100);
2754  break;
2755  case DCH_FF5: /* hundredth of a millisecond */
2756  DCH_to_char_fsec("%05d", in->fsec / 10);
2757  break;
2758  case DCH_FF6:
2759  case DCH_US: /* microsecond */
2760  DCH_to_char_fsec("%06d", in->fsec);
2761  break;
2762 #undef DCH_to_char_fsec
2763  case DCH_SSSS:
2764  sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2765  tm->tm_min * SECS_PER_MINUTE +
2766  tm->tm_sec);
2767  if (S_THth(n->suffix))
2768  str_numth(s, s, S_TH_TYPE(n->suffix));
2769  s += strlen(s);
2770  break;
2771  case DCH_tz:
2773  if (tmtcTzn(in))
2774  {
2775  /* We assume here that timezone names aren't localized */
2776  char *p = asc_tolower_z(tmtcTzn(in));
2777 
2778  strcpy(s, p);
2779  pfree(p);
2780  s += strlen(s);
2781  }
2782  break;
2783  case DCH_TZ:
2785  if (tmtcTzn(in))
2786  {
2787  strcpy(s, tmtcTzn(in));
2788  s += strlen(s);
2789  }
2790  break;
2791  case DCH_TZH:
2793  sprintf(s, "%c%02d",
2794  (tm->tm_gmtoff >= 0) ? '+' : '-',
2795  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2796  s += strlen(s);
2797  break;
2798  case DCH_TZM:
2800  sprintf(s, "%02d",
2801  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2802  s += strlen(s);
2803  break;
2804  case DCH_OF:
2806  sprintf(s, "%c%0*d",
2807  (tm->tm_gmtoff >= 0) ? '+' : '-',
2808  S_FM(n->suffix) ? 0 : 2,
2809  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2810  s += strlen(s);
2811  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2812  {
2813  sprintf(s, ":%02d",
2814  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2815  s += strlen(s);
2816  }
2817  break;
2818  case DCH_A_D:
2819  case DCH_B_C:
2821  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2822  s += strlen(s);
2823  break;
2824  case DCH_AD:
2825  case DCH_BC:
2827  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2828  s += strlen(s);
2829  break;
2830  case DCH_a_d:
2831  case DCH_b_c:
2833  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2834  s += strlen(s);
2835  break;
2836  case DCH_ad:
2837  case DCH_bc:
2839  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2840  s += strlen(s);
2841  break;
2842  case DCH_MONTH:
2844  if (!tm->tm_mon)
2845  break;
2846  if (S_TM(n->suffix))
2847  {
2848  char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2849 
2850  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2851  strcpy(s, str);
2852  else
2853  ereport(ERROR,
2854  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2855  errmsg("localized string format value too long")));
2856  }
2857  else
2858  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2859  asc_toupper_z(months_full[tm->tm_mon - 1]));
2860  s += strlen(s);
2861  break;
2862  case DCH_Month:
2864  if (!tm->tm_mon)
2865  break;
2866  if (S_TM(n->suffix))
2867  {
2868  char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2869 
2870  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2871  strcpy(s, str);
2872  else
2873  ereport(ERROR,
2874  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2875  errmsg("localized string format value too long")));
2876  }
2877  else
2878  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2879  months_full[tm->tm_mon - 1]);
2880  s += strlen(s);
2881  break;
2882  case DCH_month:
2884  if (!tm->tm_mon)
2885  break;
2886  if (S_TM(n->suffix))
2887  {
2888  char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2889 
2890  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2891  strcpy(s, str);
2892  else
2893  ereport(ERROR,
2894  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2895  errmsg("localized string format value too long")));
2896  }
2897  else
2898  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2899  asc_tolower_z(months_full[tm->tm_mon - 1]));
2900  s += strlen(s);
2901  break;
2902  case DCH_MON:
2904  if (!tm->tm_mon)
2905  break;
2906  if (S_TM(n->suffix))
2907  {
2908  char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2909 
2910  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2911  strcpy(s, str);
2912  else
2913  ereport(ERROR,
2914  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2915  errmsg("localized string format value too long")));
2916  }
2917  else
2918  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2919  s += strlen(s);
2920  break;
2921  case DCH_Mon:
2923  if (!tm->tm_mon)
2924  break;
2925  if (S_TM(n->suffix))
2926  {
2927  char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2928 
2929  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2930  strcpy(s, str);
2931  else
2932  ereport(ERROR,
2933  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2934  errmsg("localized string format value too long")));
2935  }
2936  else
2937  strcpy(s, months[tm->tm_mon - 1]);
2938  s += strlen(s);
2939  break;
2940  case DCH_mon:
2942  if (!tm->tm_mon)
2943  break;
2944  if (S_TM(n->suffix))
2945  {
2946  char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2947 
2948  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2949  strcpy(s, str);
2950  else
2951  ereport(ERROR,
2952  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2953  errmsg("localized string format value too long")));
2954  }
2955  else
2956  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2957  s += strlen(s);
2958  break;
2959  case DCH_MM:
2960  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2961  tm->tm_mon);
2962  if (S_THth(n->suffix))
2963  str_numth(s, s, S_TH_TYPE(n->suffix));
2964  s += strlen(s);
2965  break;
2966  case DCH_DAY:
2968  if (S_TM(n->suffix))
2969  {
2970  char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2971 
2972  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2973  strcpy(s, str);
2974  else
2975  ereport(ERROR,
2976  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2977  errmsg("localized string format value too long")));
2978  }
2979  else
2980  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2981  asc_toupper_z(days[tm->tm_wday]));
2982  s += strlen(s);
2983  break;
2984  case DCH_Day:
2986  if (S_TM(n->suffix))
2987  {
2988  char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2989 
2990  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2991  strcpy(s, str);
2992  else
2993  ereport(ERROR,
2994  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2995  errmsg("localized string format value too long")));
2996  }
2997  else
2998  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2999  days[tm->tm_wday]);
3000  s += strlen(s);
3001  break;
3002  case DCH_day:
3004  if (S_TM(n->suffix))
3005  {
3006  char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
3007 
3008  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3009  strcpy(s, str);
3010  else
3011  ereport(ERROR,
3012  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3013  errmsg("localized string format value too long")));
3014  }
3015  else
3016  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
3017  asc_tolower_z(days[tm->tm_wday]));
3018  s += strlen(s);
3019  break;
3020  case DCH_DY:
3022  if (S_TM(n->suffix))
3023  {
3024  char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
3025 
3026  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3027  strcpy(s, str);
3028  else
3029  ereport(ERROR,
3030  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3031  errmsg("localized string format value too long")));
3032  }
3033  else
3034  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
3035  s += strlen(s);
3036  break;
3037  case DCH_Dy:
3039  if (S_TM(n->suffix))
3040  {
3041  char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
3042 
3043  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3044  strcpy(s, str);
3045  else
3046  ereport(ERROR,
3047  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3048  errmsg("localized string format value too long")));
3049  }
3050  else
3051  strcpy(s, days_short[tm->tm_wday]);
3052  s += strlen(s);
3053  break;
3054  case DCH_dy:
3056  if (S_TM(n->suffix))
3057  {
3058  char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
3059 
3060  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3061  strcpy(s, str);
3062  else
3063  ereport(ERROR,
3064  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3065  errmsg("localized string format value too long")));
3066  }
3067  else
3068  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
3069  s += strlen(s);
3070  break;
3071  case DCH_DDD:
3072  case DCH_IDDD:
3073  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
3074  (n->key->id == DCH_DDD) ?
3075  tm->tm_yday :
3076  date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
3077  if (S_THth(n->suffix))
3078  str_numth(s, s, S_TH_TYPE(n->suffix));
3079  s += strlen(s);
3080  break;
3081  case DCH_DD:
3082  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
3083  if (S_THth(n->suffix))
3084  str_numth(s, s, S_TH_TYPE(n->suffix));
3085  s += strlen(s);
3086  break;
3087  case DCH_D:
3089  sprintf(s, "%d", tm->tm_wday + 1);
3090  if (S_THth(n->suffix))
3091  str_numth(s, s, S_TH_TYPE(n->suffix));
3092  s += strlen(s);
3093  break;
3094  case DCH_ID:
3096  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
3097  if (S_THth(n->suffix))
3098  str_numth(s, s, S_TH_TYPE(n->suffix));
3099  s += strlen(s);
3100  break;
3101  case DCH_WW:
3102  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3103  (tm->tm_yday - 1) / 7 + 1);
3104  if (S_THth(n->suffix))
3105  str_numth(s, s, S_TH_TYPE(n->suffix));
3106  s += strlen(s);
3107  break;
3108  case DCH_IW:
3109  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3110  date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
3111  if (S_THth(n->suffix))
3112  str_numth(s, s, S_TH_TYPE(n->suffix));
3113  s += strlen(s);
3114  break;
3115  case DCH_Q:
3116  if (!tm->tm_mon)
3117  break;
3118  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
3119  if (S_THth(n->suffix))
3120  str_numth(s, s, S_TH_TYPE(n->suffix));
3121  s += strlen(s);
3122  break;
3123  case DCH_CC:
3124  if (is_interval) /* straight calculation */
3125  i = tm->tm_year / 100;
3126  else
3127  {
3128  if (tm->tm_year > 0)
3129  /* Century 20 == 1901 - 2000 */
3130  i = (tm->tm_year - 1) / 100 + 1;
3131  else
3132  /* Century 6BC == 600BC - 501BC */
3133  i = tm->tm_year / 100 - 1;
3134  }
3135  if (i <= 99 && i >= -99)
3136  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
3137  else
3138  sprintf(s, "%d", i);
3139  if (S_THth(n->suffix))
3140  str_numth(s, s, S_TH_TYPE(n->suffix));
3141  s += strlen(s);
3142  break;
3143  case DCH_Y_YYY:
3144  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
3145  sprintf(s, "%d,%03d", i,
3146  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
3147  if (S_THth(n->suffix))
3148  str_numth(s, s, S_TH_TYPE(n->suffix));
3149  s += strlen(s);
3150  break;
3151  case DCH_YYYY:
3152  case DCH_IYYY:
3153  sprintf(s, "%0*d",
3154  S_FM(n->suffix) ? 0 :
3155  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
3156  (n->key->id == DCH_YYYY ?
3157  ADJUST_YEAR(tm->tm_year, is_interval) :
3159  tm->tm_mon,
3160  tm->tm_mday),
3161  is_interval)));
3162  if (S_THth(n->suffix))
3163  str_numth(s, s, S_TH_TYPE(n->suffix));
3164  s += strlen(s);
3165  break;
3166  case DCH_YYY:
3167  case DCH_IYY:
3168  sprintf(s, "%0*d",
3169  S_FM(n->suffix) ? 0 :
3170  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
3171  (n->key->id == DCH_YYY ?
3172  ADJUST_YEAR(tm->tm_year, is_interval) :
3174  tm->tm_mon,
3175  tm->tm_mday),
3176  is_interval)) % 1000);
3177  if (S_THth(n->suffix))
3178  str_numth(s, s, S_TH_TYPE(n->suffix));
3179  s += strlen(s);
3180  break;
3181  case DCH_YY:
3182  case DCH_IY:
3183  sprintf(s, "%0*d",
3184  S_FM(n->suffix) ? 0 :
3185  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
3186  (n->key->id == DCH_YY ?
3187  ADJUST_YEAR(tm->tm_year, is_interval) :
3189  tm->tm_mon,
3190  tm->tm_mday),
3191  is_interval)) % 100);
3192  if (S_THth(n->suffix))
3193  str_numth(s, s, S_TH_TYPE(n->suffix));
3194  s += strlen(s);
3195  break;
3196  case DCH_Y:
3197  case DCH_I:
3198  sprintf(s, "%1d",
3199  (n->key->id == DCH_Y ?
3200  ADJUST_YEAR(tm->tm_year, is_interval) :
3202  tm->tm_mon,
3203  tm->tm_mday),
3204  is_interval)) % 10);
3205  if (S_THth(n->suffix))
3206  str_numth(s, s, S_TH_TYPE(n->suffix));
3207  s += strlen(s);
3208  break;
3209  case DCH_RM:
3210  /* FALLTHROUGH */
3211  case DCH_rm:
3212 
3213  /*
3214  * For intervals, values like '12 month' will be reduced to 0
3215  * month and some years. These should be processed.
3216  */
3217  if (!tm->tm_mon && !tm->tm_year)
3218  break;
3219  else
3220  {
3221  int mon = 0;
3222  const char *const *months;
3223 
3224  if (n->key->id == DCH_RM)
3225  months = rm_months_upper;
3226  else
3227  months = rm_months_lower;
3228 
3229  /*
3230  * Compute the position in the roman-numeral array. Note
3231  * that the contents of the array are reversed, December
3232  * being first and January last.
3233  */
3234  if (tm->tm_mon == 0)
3235  {
3236  /*
3237  * This case is special, and tracks the case of full
3238  * interval years.
3239  */
3240  mon = tm->tm_year >= 0 ? 0 : MONTHS_PER_YEAR - 1;
3241  }
3242  else if (tm->tm_mon < 0)
3243  {
3244  /*
3245  * Negative case. In this case, the calculation is
3246  * reversed, where -1 means December, -2 November,
3247  * etc.
3248  */
3249  mon = -1 * (tm->tm_mon + 1);
3250  }
3251  else
3252  {
3253  /*
3254  * Common case, with a strictly positive value. The
3255  * position in the array matches with the value of
3256  * tm_mon.
3257  */
3258  mon = MONTHS_PER_YEAR - tm->tm_mon;
3259  }
3260 
3261  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
3262  months[mon]);
3263  s += strlen(s);
3264  }
3265  break;
3266  case DCH_W:
3267  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
3268  if (S_THth(n->suffix))
3269  str_numth(s, s, S_TH_TYPE(n->suffix));
3270  s += strlen(s);
3271  break;
3272  case DCH_J:
3273  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
3274  if (S_THth(n->suffix))
3275  str_numth(s, s, S_TH_TYPE(n->suffix));
3276  s += strlen(s);
3277  break;
3278  }
3279  }
3280 
3281  *s = '\0';
3282 }
#define a_m_STR
Definition: formatting.c:266
#define NODE_TYPE_END
Definition: formatting.c:203
uint8 type
Definition: formatting.c:197
const KeyWord * key
Definition: formatting.c:200
int tm_wday
Definition: pgtime.h:33
#define b_c_STR
Definition: formatting.c:244
#define S_THth(_s)
Definition: formatting.c:554
int tm_hour
Definition: pgtime.h:29
#define BC_STR
Definition: formatting.c:245
#define A_M_STR
Definition: formatting.c:265
static char * str_initcap_z(const char *buff, Oid collid)
Definition: formatting.c:2124
fsec_t fsec
Definition: formatting.c:500
static char * asc_tolower_z(const char *buff)
Definition: formatting.c:2130
#define AD_STR
Definition: formatting.c:240
int errcode(int sqlerrcode)
Definition: elog.c:698
struct pg_tm tm
Definition: formatting.c:499
#define p_m_STR
Definition: formatting.c:271
#define am_STR
Definition: formatting.c:268
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:2112
long int tm_gmtoff
Definition: pgtime.h:36
Definition: pgtime.h:25
static char * str_numth(char *dest, char *num, int type)
Definition: formatting.c:1557
static const char *const rm_months_upper[]
Definition: formatting.c:294
int id
Definition: formatting.c:190
#define pm_STR
Definition: formatting.c:273
static struct pg_tm tm
Definition: localtime.c:102
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define sprintf
Definition: port.h:218
void pfree(void *pointer)
Definition: mcxt.c:1169
const char *const months[]
Definition: datetime.c:65
#define NODE_TYPE_ACTION
Definition: formatting.c:204
#define ERROR
Definition: elog.h:46
char character[MAX_MULTIBYTE_CHAR_LEN+1]
Definition: formatting.c:198
char * localized_abbrev_months[12+1]
Definition: pg_locale.c:99
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4432
#define S_FM(_s)
Definition: formatting.c:560
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4487
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
const char *const days[]
Definition: datetime.c:68
#define A_D_STR
Definition: formatting.c:238
char * localized_full_days[7+1]
Definition: pg_locale.c:98
#define a_d_STR
Definition: formatting.c:239
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define bc_STR
Definition: formatting.c:246
#define DCH_to_char_fsec(frac_fmt, frac_val)
#define S_TH_TYPE(_s)
Definition: formatting.c:557
static const char *const months_full[]
Definition: formatting.c:220
int len
Definition: formatting.c:189
int date2j(int y, int m, int d)
Definition: datetime.c:269
#define ereport(elevel,...)
Definition: elog.h:157
#define ad_STR
Definition: formatting.c:241
char * localized_full_months[12+1]
Definition: pg_locale.c:100
void cache_locale_time(void)
Definition: pg_locale.c:747
#define P_M_STR
Definition: formatting.c:270
static char * asc_toupper_z(const char *buff)
Definition: formatting.c:2136
#define ADJUST_YEAR(year, is_interval)
Definition: formatting.c:236
uint8 suffix
Definition: formatting.c:199
#define tmtcTzn(_X)
Definition: formatting.c:505
int tm_year
Definition: pgtime.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:909
static char * str_toupper_z(const char *buff, Oid collid)
Definition: formatting.c:2118
#define INVALID_FOR_INTERVAL
Definition: formatting.c:527
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:4544
int i
#define S_TM(_s)
Definition: formatting.c:562
char * localized_abbrev_days[7+1]
Definition: pg_locale.c:97
int tm_yday
Definition: pgtime.h:34
#define PM_STR
Definition: formatting.c:272
#define AM_STR
Definition: formatting.c:267
#define TM_SUFFIX_LEN
Definition: formatting.c:568
int tm_sec
Definition: pgtime.h:27
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:156
int tm_min
Definition: pgtime.h:28
static const char *const rm_months_lower[]
Definition: formatting.c:297
static const char *const days_short[]
Definition: formatting.c:225
#define B_C_STR
Definition: formatting.c:243

◆ do_to_timestamp()

static void do_to_timestamp ( text date_txt,
text fmt,
Oid  collid,
bool  std,
struct pg_tm tm,
fsec_t fsec,
int *  fprec,
uint32 flags,
bool have_error 
)
static

Definition at line 4468 of file formatting.c.

References Assert, TmFromChar::bc, TmFromChar::cc, CHECK_ERROR, TmFromChar::clock, CLOCK_12_HOUR, TmFromChar::d, DateTimeParseError(), DAY, DCH_cache_fetch(), DCH_CACHE_SIZE, DCH_datetime_type(), DCH_FLAG, DCH_from_char(), DCH_index, TmFromChar::dd, TmFromChar::ddd, DEBUG_TM, DEBUG_TMFC, DTERR_FIELD_OVERFLOW, DTERR_TZDISP_OVERFLOW, DTK_DATE_M, DTK_M, ereport, errcode(), errhint(), errmsg(), ERROR, TmFromChar::ff, format, DCHCacheEntry::format, FROM_CHAR_DATE_ISOWEEK, TmFromChar::hh, HOURS_PER_DAY, i, isleap, isoweek2date(), isoweek2j(), isoweekdate2date(), TmFromChar::j, j2date(), MAX_TZDISP_HOUR, TmFromChar::mi, MINS_PER_HOUR, TmFromChar::mm, TmFromChar::mode, MONTH, MONTHS_PER_YEAR, TmFromChar::ms, palloc(), parse_format(), pfree(), TmFromChar::pm, psprintf(), RETURN_ERROR, SECS_PER_HOUR, SECS_PER_MINUTE, TmFromChar::ss, TmFromChar::ssss, STD_FLAG, text_to_cstring(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, pg_tm::tm_zone, TmFromChar::tzh, TmFromChar::tzm, TmFromChar::tzsign, TmFromChar::us, USECS_PER_SEC, ValidateDate(), VARSIZE_ANY_EXHDR, TmFromChar::w, TmFromChar::ww, YEAR, TmFromChar::year, TmFromChar::yysz, ZERO_tm, and ZERO_tmfc.

Referenced by parse_datetime(), to_date(), and to_timestamp().

4471 {
4472  FormatNode *format = NULL;
4473  TmFromChar tmfc;
4474  int fmt_len;
4475  char *date_str;
4476  int fmask;
4477  bool incache = false;
4478 
4479  Assert(tm != NULL);
4480  Assert(fsec != NULL);
4481 
4482  date_str = text_to_cstring(date_txt);
4483 
4484  ZERO_tmfc(&tmfc);
4485  ZERO_tm(tm);
4486  *fsec = 0;
4487  if (fprec)
4488  *fprec = 0;
4489  if (flags)
4490  *flags = 0;
4491  fmask = 0; /* bit mask for ValidateDate() */
4492 
4493  fmt_len = VARSIZE_ANY_EXHDR(fmt);
4494 
4495  if (fmt_len)
4496  {
4497  char *fmt_str;
4498 
4499  fmt_str = text_to_cstring(fmt);
4500 
4501  if (fmt_len > DCH_CACHE_SIZE)
4502  {
4503  /*
4504  * Allocate new memory if format picture is bigger than static
4505  * cache and do not use cache (call parser always)
4506  */
4507  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4508 
4509  parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index,
4510  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
4511  }
4512  else
4513  {
4514  /*
4515  * Use cache buffers
4516  */
4517  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, std);
4518 
4519  incache = true;
4520  format = ent->format;
4521  }
4522 
4523 #ifdef DEBUG_TO_FROM_CHAR
4524  /* dump_node(format, fmt_len); */
4525  /* dump_index(DCH_keywords, DCH_index); */
4526 #endif
4527 
4528  DCH_from_char(format, date_str, &tmfc, collid, std, have_error);
4529  CHECK_ERROR;
4530 
4531  pfree(fmt_str);
4532 
4533  if (flags)
4534  *flags = DCH_datetime_type(format, have_error);
4535 
4536  if (!incache)
4537  {
4538  pfree(format);
4539  format = NULL;
4540  }
4541 
4542  CHECK_ERROR;
4543  }
4544 
4545  DEBUG_TMFC(&tmfc);
4546 
4547  /*
4548  * Convert to_date/to_timestamp input fields to standard 'tm'
4549  */
4550  if (tmfc.ssss)
4551  {
4552  int x = tmfc.ssss;
4553 
4554  tm->tm_hour = x / SECS_PER_HOUR;
4555  x %= SECS_PER_HOUR;
4556  tm->tm_min = x / SECS_PER_MINUTE;
4557  x %= SECS_PER_MINUTE;
4558  tm->tm_sec = x;
4559  }
4560 
4561  if (tmfc.ss)
4562  tm->tm_sec = tmfc.ss;
4563  if (tmfc.mi)
4564  tm->tm_min = tmfc.mi;
4565  if (tmfc.hh)
4566  tm->tm_hour = tmfc.hh;
4567 
4568  if (tmfc.clock == CLOCK_12_HOUR)
4569  {
4570  if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
4571  {
4573  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4574  errmsg("hour \"%d\" is invalid for the 12-hour clock",
4575  tm->tm_hour),
4576  errhint("Use the 24-hour clock, or give an hour between 1 and 12."))));
4577  }
4578 
4579  if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
4580  tm->tm_hour += HOURS_PER_DAY / 2;
4581  else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
4582  tm->tm_hour = 0;
4583  }
4584 
4585  if (tmfc.year)
4586  {
4587  /*
4588  * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
4589  * the year in the given century. Keep in mind that the 21st century
4590  * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
4591  * 600BC to 501BC.
4592  */
4593  if (tmfc.cc && tmfc.yysz <= 2)
4594  {
4595  if (tmfc.bc)
4596  tmfc.cc = -tmfc.cc;
4597  tm->tm_year = tmfc.year % 100;
4598  if (tm->tm_year)
4599  {
4600  if (tmfc.cc >= 0)
4601  tm->tm_year += (tmfc.cc - 1) * 100;
4602  else
4603  tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
4604  }
4605  else
4606  {
4607  /* find century year for dates ending in "00" */
4608  tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
4609  }
4610  }
4611  else
4612  {
4613  /* If a 4-digit year is provided, we use that and ignore CC. */
4614  tm->tm_year = tmfc.year;
4615  if (tmfc.bc)
4616  tm->tm_year = -tm->tm_year;
4617  /* correct for our representation of BC years */
4618  if (tm->tm_year < 0)
4619  tm->tm_year++;
4620  }
4621  fmask |= DTK_M(YEAR);
4622  }
4623  else if (tmfc.cc)
4624  {
4625  /* use first year of century */
4626  if (tmfc.bc)
4627  tmfc.cc = -tmfc.cc;
4628  if (tmfc.cc >= 0)
4629  /* +1 because 21st century started in 2001 */
4630  tm->tm_year = (tmfc.cc - 1) * 100 + 1;
4631  else
4632  /* +1 because year == 599 is 600 BC */
4633  tm->tm_year = tmfc.cc * 100 + 1;
4634  fmask |= DTK_M(YEAR);
4635  }
4636 
4637  if (tmfc.j)
4638  {
4639  j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4640  fmask |= DTK_DATE_M;
4641  }
4642 
4643  if (tmfc.ww)
4644  {
4645  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
4646  {
4647  /*
4648  * If tmfc.d is not set, then the date is left at the beginning of
4649  * the ISO week (Monday).
4650  */
4651  if (tmfc.d)
4652  isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4653  else
4654  isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4655  fmask |= DTK_DATE_M;
4656  }
4657  else
4658  tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
4659  }
4660 
4661  if (tmfc.w)
4662  tmfc.dd = (tmfc.w - 1) * 7 + 1;
4663  if (tmfc.dd)
4664  {
4665  tm->tm_mday = tmfc.dd;
4666  fmask |= DTK_M(DAY);
4667  }
4668  if (tmfc.mm)
4669  {
4670  tm->tm_mon = tmfc.mm;
4671  fmask |= DTK_M(MONTH);
4672  }
4673 
4674  if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
4675  {
4676  /*
4677  * The month and day field have not been set, so we use the
4678  * day-of-year field to populate them. Depending on the date mode,
4679  * this field may be interpreted as a Gregorian day-of-year, or an ISO
4680  * week date day-of-year.
4681  */
4682 
4683  if (!tm->tm_year && !tmfc.bc)
4684  {
4686  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4687  errmsg("cannot calculate day of year without year information"))));
4688  }
4689 
4690  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
4691  {
4692  int j0; /* zeroth day of the ISO year, in Julian */
4693 
4694  j0 = isoweek2j(tm->tm_year, 1) - 1;
4695 
4696  j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4697  fmask |= DTK_DATE_M;
4698  }
4699  else
4700  {
4701  const int *y;
4702  int i;
4703 
4704  static const int ysum[2][13] = {
4705  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
4706  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
4707 
4708  y = ysum[isleap(tm->tm_year)];
4709 
4710  for (i = 1; i <= MONTHS_PER_YEAR; i++)
4711  {
4712  if (tmfc.ddd <= y[i])
4713  break;
4714  }
4715  if (tm->tm_mon <= 1)
4716  tm->tm_mon = i;
4717 
4718  if (tm->tm_mday <= 1)
4719  tm->tm_mday = tmfc.ddd - y[i - 1];
4720 
4721  fmask |= DTK_M(MONTH) | DTK_M(DAY);
4722  }
4723  }
4724 
4725  if (tmfc.ms)
4726  *fsec += tmfc.ms * 1000;
4727  if (tmfc.us)
4728  *fsec += tmfc.us;
4729  if (fprec)
4730  *fprec = tmfc.ff; /* fractional precision, if specified */
4731 
4732  /* Range-check date fields according to bit mask computed above */
4733  if (fmask != 0)
4734  {
4735  /* We already dealt with AD/BC, so pass isjulian = true */
4736  int dterr = ValidateDate(fmask, true, false, false, tm);
4737 
4738  if (dterr != 0)
4739  {
4740  /*
4741  * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
4742  * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
4743  * irrelevant hint about datestyle.
4744  */
4745  RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
4746  }
4747  }
4748 
4749  /* Range-check time fields too */
4750  if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
4751  tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
4752  tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
4753  *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
4754  {
4755  RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
4756  }
4757 
4758  /* Save parsed time-zone into tm->tm_zone if it was specified */
4759  if (tmfc.tzsign)
4760  {
4761  char *tz;
4762 
4763  if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
4764  tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
4765  {
4766  RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, date_str, "timestamp"));
4767  }
4768 
4769  tz = psprintf("%c%02d:%02d",
4770  tmfc.tzsign > 0 ? '+' : '-', tmfc.tzh, tmfc.tzm);
4771 
4772  tm->tm_zone = tz;
4773  }
4774 
4775  DEBUG_TM(tm);
4776 
4777 on_error:
4778 
4779  if (format && !incache)
4780  pfree(format);
4781 
4782  pfree(date_str);
4783 }
#define DEBUG_TM(_X)
Definition: formatting.c:490
#define DAY
Definition: datetime.h:94
int errhint(const char *fmt,...)
Definition: elog.c:1156
void DateTimeParseError(int dterr, const char *str, const char *datatype)
Definition: datetime.c:3768
#define USECS_PER_SEC
Definition: timestamp.h:94
static int DCH_datetime_type(FormatNode *node, bool *have_error)
Definition: formatting.c:3810
#define YEAR
Definition: datetime.h:93
static void DCH_from_char(FormatNode *node, const char *in, TmFromChar *out, Oid collid, bool std, bool *have_error)
Definition: formatting.c:3296
int tm_hour
Definition: pgtime.h:29
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define isleap(y)
Definition: datetime.h:271
static const KeySuffix DCH_suff[]
Definition: formatting.c:570
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:944
int errcode(int sqlerrcode)
Definition: elog.c:698
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:4414
FromCharDateMode mode
Definition: formatting.c:444
#define CHECK_ERROR
Definition: formatting.c:131
#define DTK_DATE_M
Definition: datetime.h:192
#define MINS_PER_HOUR
Definition: timestamp.h:89
#define MAX_TZDISP_HOUR
Definition: timestamp.h:103
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
void pfree(void *pointer)
Definition: mcxt.c:1169
#define DCH_CACHE_SIZE
Definition: formatting.c:402
#define ERROR
Definition: elog.h:46
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:281
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:412
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:1324
const char * tm_zone
Definition: pgtime.h:37
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define CLOCK_12_HOUR
Definition: formatting.c:213
#define MONTH
Definition: datetime.h:92
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:284
void isoweek2date(int woy, int *year, int *mon, int *mday)
Definition: timestamp.c:4401
#define ZERO_tmfc(_X)
Definition: formatting.c:470
int isoweek2j(int year, int week)
Definition: timestamp.c:4381
#define DCH_FLAG
Definition: formatting.c:141
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define DEBUG_TMFC(_X)
Definition: formatting.c:489
char * text_to_cstring(const text *t)
Definition: varlena.c:223
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
static const KeyWord DCH_keywords[]
Definition: formatting.c:774
int i
#define STD_FLAG
Definition: formatting.c:143
#define DTK_M(t)
Definition: datetime.h:188
static char format
int tm_sec
Definition: pgtime.h:27
#define ZERO_tm(_X)
Definition: formatting.c:508
int tm_min
Definition: pgtime.h:28
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:3995
#define RETURN_ERROR(throw_error)
Definition: formatting.c:118
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2480

◆ fill_str()

static char * fill_str ( char *  str,
int  c,
int  max 
)
static

Definition at line 4792 of file formatting.c.

References generate_unaccent_rules::str.

Referenced by float4_to_char(), float8_to_char(), int4_to_char(), int8_to_char(), int_to_roman(), and numeric_to_char().

4793 {
4794  memset(str, c, max);
4795  *(str + max) = '\0';
4796  return str;
4797 }
char * c

◆ float4_to_char()

Datum float4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6478 of file formatting.c.

References fill_str(), format, int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, NUMDesc::multi, NUM_TOCHAR_finish, NUM_TOCHAR_prepare, palloc(), PG_GETARG_FLOAT4, PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, psprintf(), sign, val, and value.

6479 {
6481  text *fmt = PG_GETARG_TEXT_PP(1);
6482  NUMDesc Num;
6483  FormatNode *format;
6484  text *result;
6485  bool shouldFree;
6486  int out_pre_spaces = 0,
6487  sign = 0;
6488  char *numstr,
6489  *p;
6490 
6492 
6493  if (IS_ROMAN(&Num))
6494  numstr = int_to_roman((int) rint(value));
6495  else if (IS_EEEE(&Num))
6496  {
6497  if (isnan(value) || isinf(value))
6498  {
6499  /*
6500  * Allow 6 characters for the leading sign, the decimal point,
6501  * "e", the exponent's sign and two exponent digits.
6502  */
6503  numstr = (char *) palloc(Num.pre + Num.post + 7);
6504  fill_str(numstr, '#', Num.pre + Num.post + 6);
6505  *numstr = ' ';
6506  *(numstr + Num.pre + 1) = '.';
6507  }
6508  else
6509  {
6510  numstr = psprintf("%+.*e", Num.post, value);
6511 
6512  /*
6513  * Swap a leading positive sign for a space.
6514  */
6515  if (*numstr == '+')
6516  *numstr = ' ';
6517  }
6518  }
6519  else
6520  {
6521  float4 val = value;
6522  char *orgnum;
6523  int numstr_pre_len;
6524 
6525  if (IS_MULTI(&Num))
6526  {
6527  float multi = pow((double) 10, (double) Num.multi);
6528 
6529  val = value * multi;
6530  Num.pre += Num.multi;
6531  }
6532 
6533  orgnum = psprintf("%.0f", fabs(val));
6534  numstr_pre_len = strlen(orgnum);
6535 
6536  /* adjust post digits to fit max float digits */
6537  if (numstr_pre_len >= FLT_DIG)
6538  Num.post = 0;
6539  else if (numstr_pre_len + Num.post > FLT_DIG)
6540  Num.post = FLT_DIG - numstr_pre_len;
6541  orgnum = psprintf("%.*f", Num.post, val);
6542 
6543  if (*orgnum == '-')
6544  { /* < 0 */
6545  sign = '-';
6546  numstr = orgnum + 1;
6547  }
6548  else
6549  {
6550  sign = '+';
6551  numstr = orgnum;
6552  }
6553 
6554  if ((p = strchr(numstr, '.')))
6555  numstr_pre_len = p - numstr;
6556  else
6557  numstr_pre_len = strlen(numstr);
6558 
6559  /* needs padding? */
6560  if (numstr_pre_len < Num.pre)
6561  out_pre_spaces = Num.pre - numstr_pre_len;
6562  /* overflowed prefix digit format? */
6563  else if (numstr_pre_len > Num.pre)
6564  {
6565  numstr = (char *) palloc(Num.pre + Num.post + 2);
6566  fill_str(numstr, '#', Num.pre + Num.post + 1);
6567  *(numstr + Num.pre) = '.';
6568  }
6569  }
6570 
6572  PG_RETURN_TEXT_P(result);
6573 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define IS_EEEE(_f)
Definition: formatting.c:377
#define NUM_TOCHAR_finish
Definition: formatting.c:6071
#define IS_ROMAN(_f)
Definition: formatting.c:375
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define NUM_TOCHAR_prepare
Definition: formatting.c:6058
#define IS_MULTI(_f)
Definition: formatting.c:376
char sign
Definition: informix.c:668
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:4792
static char * int_to_roman(int number)
Definition: formatting.c:4992
int pre
Definition: formatting.c:328
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
float float4
Definition: c.h:564
static struct @143 value
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
int post
Definition: formatting.c:328
void * palloc(Size size)
Definition: mcxt.c:1062
int multi
Definition: formatting.c:328
Definition: c.h:621
static char format
long val
Definition: informix.c:664

◆ float8_to_char()

Datum float8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6580 of file formatting.c.

References fill_str(), format, int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, NUMDesc::multi, NUM_TOCHAR_finish, NUM_TOCHAR_prepare, palloc(), PG_GETARG_FLOAT8, PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, psprintf(), sign, val, and value.

6581 {
6583  text *fmt = PG_GETARG_TEXT_PP(1);
6584  NUMDesc Num;
6585  FormatNode *format;
6586  text *result;
6587  bool shouldFree;
6588  int out_pre_spaces = 0,
6589  sign = 0;
6590  char *numstr,
6591  *p;
6592 
6594 
6595  if (IS_ROMAN(&Num))
6596  numstr = int_to_roman((int) rint(value));
6597  else if (IS_EEEE(&Num))
6598  {
6599  if (isnan(value) || isinf(value))
6600  {
6601  /*
6602  * Allow 6 characters for the leading sign, the decimal point,
6603  * "e", the exponent's sign and two exponent digits.
6604  */
6605  numstr = (char *) palloc(Num.pre + Num.post + 7);
6606  fill_str(numstr, '#', Num.pre + Num.post + 6);
6607  *numstr = ' ';
6608  *(numstr + Num.pre + 1) = '.';
6609  }
6610  else
6611  {
6612  numstr = psprintf("%+.*e", Num.post, value);
6613 
6614  /*
6615  * Swap a leading positive sign for a space.
6616  */
6617  if (*numstr == '+')
6618  *numstr = ' ';
6619  }
6620  }
6621  else
6622  {
6623  float8 val = value;
6624  char *orgnum;
6625  int numstr_pre_len;
6626 
6627  if (IS_MULTI(&Num))
6628  {
6629  double multi = pow((double) 10, (double) Num.multi);
6630 
6631  val = value * multi;
6632  Num.pre += Num.multi;
6633  }
6634 
6635  orgnum = psprintf("%.0f", fabs(val));
6636  numstr_pre_len = strlen(orgnum);
6637 
6638  /* adjust post digits to fit max double digits */
6639  if (numstr_pre_len >= DBL_DIG)
6640  Num.post = 0;
6641  else if (numstr_pre_len + Num.post > DBL_DIG)
6642  Num.post = DBL_DIG - numstr_pre_len;
6643  orgnum = psprintf("%.*f", Num.post, val);
6644 
6645  if (*orgnum == '-')
6646  { /* < 0 */
6647  sign = '-';
6648  numstr = orgnum + 1;
6649  }
6650  else
6651  {
6652  sign = '+';
6653  numstr = orgnum;
6654  }
6655 
6656  if ((p = strchr(numstr, '.')))
6657  numstr_pre_len = p - numstr;
6658  else
6659  numstr_pre_len = strlen(numstr);
6660 
6661  /* needs padding? */
6662  if (numstr_pre_len < Num.pre)
6663  out_pre_spaces = Num.pre - numstr_pre_len;
6664  /* overflowed prefix digit format? */
6665  else if (numstr_pre_len > Num.pre)
6666  {
6667  numstr = (char *) palloc(Num.pre + Num.post + 2);
6668  fill_str(numstr, '#', Num.pre + Num.post + 1);
6669  *(numstr + Num.pre) = '.';
6670  }
6671  }
6672 
6674  PG_RETURN_TEXT_P(result);
6675 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define IS_EEEE(_f)
Definition: formatting.c:377
#define NUM_TOCHAR_finish
Definition: formatting.c:6071
#define IS_ROMAN(_f)
Definition: formatting.c:375
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define NUM_TOCHAR_prepare
Definition: formatting.c:6058
double float8
Definition: c.h:565
#define IS_MULTI(_f)
Definition: formatting.c:376
char sign
Definition: informix.c:668
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:4792
static char * int_to_roman(int number)
Definition: formatting.c:4992
int pre
Definition: formatting.c:328
static struct @143 value
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
int post
Definition: formatting.c:328
void * palloc(Size size)
Definition: mcxt.c:1062
int multi
Definition: formatting.c:328
Definition: c.h:621
static char format
long val
Definition: informix.c:664

◆ from_char_parse_int()

static int from_char_parse_int ( int *  dest,
const char **  src,
FormatNode node,
bool have_error 
)
static

Definition at line 2447 of file formatting.c.

References from_char_parse_int_len(), FormatNode::key, and KeyWord::len.

Referenced by DCH_from_char().

2448 {
2449  return from_char_parse_int_len(dest, src, node->key->len, node, have_error);
2450 }
const KeyWord * key
Definition: formatting.c:200
int len
Definition: formatting.c:189
static int from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node, bool *have_error)
Definition: formatting.c:2344

◆ from_char_parse_int_len()

static int from_char_parse_int_len ( int *  dest,
const char **  src,
const int  len,
FormatNode node,
bool have_error 
)
static

Definition at line 2344 of file formatting.c.

References Assert, CHECK_ERROR, DCH_MAX_ITEM_SIZ, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, from_char_set_int(), init, is_next_separator(), FormatNode::key, KeyWord::name, RETURN_ERROR, S_FM, strlcpy(), strspace_len(), and FormatNode::suffix.

Referenced by DCH_from_char(), and from_char_parse_int().

2346 {
2347  long result;
2348  char copy[DCH_MAX_ITEM_SIZ + 1];
2349  const char *init = *src;
2350  int used;
2351 
2352  /*
2353  * Skip any whitespace before parsing the integer.
2354  */
2355  *src += strspace_len(*src);
2356 
2357  Assert(len <= DCH_MAX_ITEM_SIZ);
2358  used = (int) strlcpy(copy, *src, len + 1);
2359 
2360  if (S_FM(node->suffix) || is_next_separator(node))
2361  {
2362  /*
2363  * This node is in Fill Mode, or the next node is known to be a
2364  * non-digit value, so we just slurp as many characters as we can get.
2365  */
2366  char *endptr;
2367 
2368  errno = 0;
2369  result = strtol(init, &endptr, 10);
2370  *src = endptr;
2371  }
2372  else
2373  {
2374  /*
2375  * We need to pull exactly the number of characters given in 'len' out
2376  * of the string, and convert those.
2377  */
2378  char *last;
2379 
2380  if (used < len)
2382  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2383  errmsg("source string too short for \"%s\" "
2384  "formatting field",
2385  node->key->name),
2386  errdetail("Field requires %d characters, "
2387  "but only %d remain.",
2388  len, used),
2389  errhint("If your source string is not fixed-width, "
2390  "try using the \"FM\" modifier."))));
2391 
2392  errno = 0;
2393  result = strtol(copy, &last, 10);
2394  used = last - copy;
2395 
2396  if (used > 0 && used < len)
2398  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2399  errmsg("invalid value \"%s\" for \"%s\"",
2400  copy, node->key->name),
2401  errdetail("Field requires %d characters, "
2402  "but only %d could be parsed.",
2403  len, used),
2404  errhint("If your source string is not fixed-width, "
2405  "try using the \"FM\" modifier."))));
2406 
2407  *src += used;
2408  }
2409 
2410  if (*src == init)
2412  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2413  errmsg("invalid value \"%s\" for \"%s\"",
2414  copy, node->key->name),
2415  errdetail("Value must be an integer."))));
2416 
2417  if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2419  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2420  errmsg("value for \"%s\" in source string is out of range",
2421  node->key->name),
2422  errdetail("Value must be in the range %d to %d.",
2423  INT_MIN, INT_MAX))));
2424 
2425  if (dest != NULL)
2426  {
2427  from_char_set_int(dest, (int) result, node, have_error);
2428  CHECK_ERROR;
2429  }
2430 
2431  return *src - init;
2432 
2433 on_error:
2434  return -1;
2435 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
static int strspace_len(const char *str)
Definition: formatting.c:2255
const KeyWord * key
Definition: formatting.c:200
int errcode(int sqlerrcode)
Definition: elog.c:698
#define CHECK_ERROR
Definition: formatting.c:131
#define ERROR
Definition: elog.h:46
static bool is_next_separator(FormatNode *n)
Definition: formatting.c:2198
#define S_FM(_s)
Definition: formatting.c:560
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define init()
const char * name
Definition: formatting.c:188
#define ereport(elevel,...)
Definition: elog.h:157
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:804
uint8 suffix
Definition: formatting.c:199
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:156
static void from_char_set_int(int *dest, const int value, const FormatNode *node, bool *have_error)
Definition: formatting.c:2303