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 "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.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 ONE_UPPER   1 /* Name */
 
#define ALL_UPPER   2 /* NAME */
 
#define ALL_LOWER   3 /* name */
 
#define MAX_MONTH_LEN   9
 
#define MAX_MON_LEN   3
 
#define MAX_DAY_LEN   9
 
#define MAX_DY_LEN   3
 
#define MAX_RM_LEN   4
 
#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, char *in, TmFromChar *out, 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 (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, char **src, const int len, FormatNode *node, bool *have_error)
 
static int from_char_parse_int (int *dest, char **src, FormatNode *node, bool *have_error)
 
static int seq_search (char *name, const char *const *array, int type, int max, int *len)
 
static int from_char_seq_search (int *dest, char **src, const char *const *array, int type, int max, FormatNode *node, bool *have_error)
 
static void do_to_timestamp (text *date_txt, text *fmt, 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, 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 239 of file formatting.c.

Referenced by DCH_to_char().

◆ a_d_STR

#define a_d_STR   "a.d."

Definition at line 240 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().

◆ a_m_STR

#define a_m_STR   "a.m."

Definition at line 267 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().

◆ ad_STR

#define ad_STR   "ad"

Definition at line 242 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 237 of file formatting.c.

Referenced by DCH_to_char().

◆ ALL_LOWER

#define ALL_LOWER   3 /* name */

Definition at line 322 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

◆ ALL_UPPER

#define ALL_UPPER   2 /* NAME */

Definition at line 321 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

◆ AM_STR

#define AM_STR   "AM"

Definition at line 268 of file formatting.c.

Referenced by DCH_to_char().

◆ am_STR

#define am_STR   "am"

Definition at line 269 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 4984 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 244 of file formatting.c.

Referenced by DCH_to_char().

◆ b_c_STR

#define b_c_STR   "b.c."

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().

◆ bc_STR

#define bc_STR   "bc"

Definition at line 247 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 132 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 214 of file formatting.c.

Referenced by DCH_from_char(), and do_to_timestamp().

◆ CLOCK_24_HOUR

#define CLOCK_24_HOUR   0

Definition at line 213 of file formatting.c.

◆ DCH_CACHE_ENTRIES

#define DCH_CACHE_ENTRIES   20

Definition at line 418 of file formatting.c.

Referenced by DCH_cache_getnew().

◆ DCH_CACHE_OVERHEAD

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

Definition at line 408 of file formatting.c.

◆ DCH_CACHE_SIZE

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

Definition at line 413 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 1033 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 */

◆ DCH_S_FM

#define DCH_S_FM   0x01

Definition at line 555 of file formatting.c.

◆ DCH_S_SP

#define DCH_S_SP   0x08

Definition at line 558 of file formatting.c.

◆ DCH_S_TH

#define DCH_S_TH   0x02

Definition at line 556 of file formatting.c.

◆ DCH_S_th

#define DCH_S_th   0x04

Definition at line 557 of file formatting.c.

◆ DCH_S_TM

#define DCH_S_TM   0x10

Definition at line 559 of file formatting.c.

◆ DCH_TIMED

#define DCH_TIMED   0x02

Definition at line 1034 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:565
#define sprintf
Definition: port.h:194
#define S_TH_TYPE(_s)
Definition: formatting.c:568

Referenced by DCH_to_char().

◆ DCH_ZONED

#define DCH_ZONED   0x04

Definition at line 1035 of file formatting.c.

Referenced by DCH_datetime_type(), and parse_datetime().

◆ DEBUG_TM

#define DEBUG_TM (   _X)

Definition at line 501 of file formatting.c.

Referenced by do_to_timestamp().

◆ DEBUG_TMFC

#define DEBUG_TMFC (   _X)

Definition at line 500 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:974
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
int errmsg(const char *fmt,...)
Definition: elog.c:784

Definition at line 538 of file formatting.c.

Referenced by DCH_to_char().

◆ IS_BLANK

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

Definition at line 380 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 381 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 378 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 383 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 385 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:379

Definition at line 5195 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 379 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 151 of file formatting.c.

Referenced by index_seq_search().

◆ KeyWord_INDEX_SIZE

#define KeyWord_INDEX_SIZE   ('~' - ' ')

Definition at line 150 of file formatting.c.

◆ MAX_DAY_LEN

#define MAX_DAY_LEN   9

Definition at line 326 of file formatting.c.

Referenced by DCH_from_char().

◆ MAX_DY_LEN

#define MAX_DY_LEN   3

Definition at line 327 of file formatting.c.

Referenced by DCH_from_char().

◆ MAX_MON_LEN

#define MAX_MON_LEN   3

Definition at line 325 of file formatting.c.

Referenced by DCH_from_char().

◆ MAX_MONTH_LEN

#define MAX_MONTH_LEN   9

Definition at line 324 of file formatting.c.

Referenced by DCH_from_char().

◆ MAX_RM_LEN

#define MAX_RM_LEN   4

Definition at line 328 of file formatting.c.

Referenced by DCH_from_char().

◆ NODE_TYPE_ACTION

#define NODE_TYPE_ACTION   2

◆ NODE_TYPE_CHAR

#define NODE_TYPE_CHAR   3

Definition at line 206 of file formatting.c.

Referenced by parse_format().

◆ NODE_TYPE_END

#define NODE_TYPE_END   1

◆ NODE_TYPE_SEPARATOR

#define NODE_TYPE_SEPARATOR   4

Definition at line 207 of file formatting.c.

Referenced by DCH_from_char(), and parse_format().

◆ NODE_TYPE_SPACE

#define NODE_TYPE_SPACE   5

Definition at line 208 of file formatting.c.

Referenced by DCH_from_char(), and parse_format().

◆ NUM_CACHE_ENTRIES

#define NUM_CACHE_ENTRIES   20

Definition at line 419 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 410 of file formatting.c.

◆ NUM_CACHE_SIZE

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

Definition at line 415 of file formatting.c.

Referenced by NUM_cache(), and NUM_cache_getnew().

◆ NUM_F_BLANK

#define NUM_F_BLANK   (1 << 4)

Definition at line 357 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_BRACKET

#define NUM_F_BRACKET   (1 << 7)

Definition at line 360 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_DECIMAL

#define NUM_F_DECIMAL   (1 << 1)

Definition at line 354 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_EEEE

#define NUM_F_EEEE   (1 << 14)

Definition at line 367 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_FILLMODE

#define NUM_F_FILLMODE   (1 << 5)

Definition at line 358 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_LDECIMAL

#define NUM_F_LDECIMAL   (1 << 2)

Definition at line 355 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_LSIGN

#define NUM_F_LSIGN   (1 << 6)

Definition at line 359 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_MINUS

#define NUM_F_MINUS   (1 << 8)

Definition at line 361 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 366 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_MULTI

#define NUM_F_MULTI   (1 << 11)

Definition at line 364 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_PLUS

#define NUM_F_PLUS   (1 << 9)

Definition at line 362 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 365 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_F_ROMAN

#define NUM_F_ROMAN   (1 << 10)

Definition at line 363 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

◆ NUM_F_ZERO

#define NUM_F_ZERO   (1 << 3)

Definition at line 356 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_FLAG

#define NUM_FLAG   0x2 /* NUMBER flag */

Definition at line 143 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 371 of file formatting.c.

Referenced by NUMDesc_prepare().

◆ NUM_LSIGN_POST

#define NUM_LSIGN_POST   1

Definition at line 370 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 158 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:302
#define VARHDRSZ
Definition: c.h:555
#define PG_GET_COLLATION()
Definition: fmgr.h:193
char sign
Definition: informix.c:688
static char format
Definition: pg_basebackup.c:85
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:5409

Definition at line 5903 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:555
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
Definition: formatting.c:4766
void * palloc0(Size size)
Definition: mcxt.c:980
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define NUM_MAX_ITEM_SIZ
Definition: formatting.c:158
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
Definition: c.h:549

Definition at line 5890 of file formatting.c.

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

◆ ONE_UPPER

#define ONE_UPPER   1 /* Name */

Definition at line 320 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

◆ OVERLOAD_TEST

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

Definition at line 4983 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 271 of file formatting.c.

Referenced by DCH_to_char().

◆ p_m_STR

#define p_m_STR   "p.m."

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().

◆ pm_STR

#define pm_STR   "pm"

Definition at line 274 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 119 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 571 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 572 of file formatting.c.

◆ S_TH

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

Definition at line 566 of file formatting.c.

◆ S_th

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

Definition at line 567 of file formatting.c.

◆ S_TH_TYPE

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

Definition at line 568 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 565 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 573 of file formatting.c.

Referenced by 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:565
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802

Definition at line 2157 of file formatting.c.

Referenced by DCH_from_char().

◆ STD_FLAG

#define STD_FLAG   0x4 /* STANDARD flag */

Definition at line 144 of file formatting.c.

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

◆ SUFFTYPE_POSTFIX

#define SUFFTYPE_POSTFIX   2

Definition at line 211 of file formatting.c.

Referenced by parse_format().

◆ SUFFTYPE_PREFIX

#define SUFFTYPE_PREFIX   1

Definition at line 210 of file formatting.c.

Referenced by parse_format().

◆ TH_LOWER

#define TH_LOWER   2

Definition at line 331 of file formatting.c.

Referenced by NUM_processor().

◆ TH_UPPER

#define TH_UPPER   1

Definition at line 330 of file formatting.c.

Referenced by get_th(), and NUM_processor().

◆ TM_SUFFIX_LEN

#define TM_SUFFIX_LEN   2

Definition at line 579 of file formatting.c.

Referenced by DCH_to_char().

◆ tmtcFsec

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

Definition at line 517 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 515 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 516 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 519 of file formatting.c.

Referenced by do_to_timestamp().

◆ ZERO_tmfc

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

Definition at line 481 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:515

Definition at line 527 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 4631 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 622 of file formatting.c.

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

◆ FromCharDateMode

Enumerator
FROM_CHAR_DATE_NONE 
FROM_CHAR_DATE_GREGORIAN 
FROM_CHAR_DATE_ISOWEEK 

Definition at line 180 of file formatting.c.

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

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

739 {
740  NUM_COMMA,
741  NUM_DEC,
742  NUM_0,
743  NUM_9,
744  NUM_B,
745  NUM_C,
746  NUM_D,
747  NUM_E,
748  NUM_FM,
749  NUM_G,
750  NUM_L,
751  NUM_MI,
752  NUM_PL,
753  NUM_PR,
754  NUM_RN,
755  NUM_SG,
756  NUM_SP,
757  NUM_S,
758  NUM_TH,
759  NUM_V,
760  NUM_b,
761  NUM_c,
762  NUM_d,
763  NUM_e,
764  NUM_fm,
765  NUM_g,
766  NUM_l,
767  NUM_mi,
768  NUM_pl,
769  NUM_pr,
770  NUM_rn,
771  NUM_sg,
772  NUM_sp,
773  NUM_s,
774  NUM_th,
775  NUM_v,
776 
777  /* last */
778  _NUM_last_
779 } NUM_poz;
NUM_poz
Definition: formatting.c:738

Function Documentation

◆ adjust_partial_year_to_2020()

static int adjust_partial_year_to_2020 ( int  year)
static

Definition at line 2238 of file formatting.c.

Referenced by DCH_from_char().

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

◆ asc_initcap()

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

Definition at line 2088 of file formatting.c.

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

Referenced by str_initcap().

2089 {
2090  char *result;
2091  char *p;
2092  int wasalnum = false;
2093 
2094  if (!buff)
2095  return NULL;
2096 
2097  result = pnstrdup(buff, nbytes);
2098 
2099  for (p = result; *p; p++)
2100  {
2101  char c;
2102 
2103  if (wasalnum)
2104  *p = c = pg_ascii_tolower((unsigned char) *p);
2105  else
2106  *p = c = pg_ascii_toupper((unsigned char) *p);
2107  /* we don't trust isalnum() here */
2108  wasalnum = ((c >= 'A' && c <= 'Z') ||
2109  (c >= 'a' && c <= 'z') ||
2110  (c >= '0' && c <= '9'));
2111  }
2112 
2113  return result;
2114 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
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 2042 of file formatting.c.

References pg_ascii_tolower(), and pnstrdup().

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

2043 {
2044  char *result;
2045  char *p;
2046 
2047  if (!buff)
2048  return NULL;
2049 
2050  result = pnstrdup(buff, nbytes);
2051 
2052  for (p = result; *p; p++)
2053  *p = pg_ascii_tolower((unsigned char) *p);
2054 
2055  return result;
2056 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
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 2137 of file formatting.c.

References asc_tolower().

Referenced by DCH_to_char(), and NUM_processor().

2138 {
2139  return asc_tolower(buff, strlen(buff));
2140 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2042

◆ asc_toupper()

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

Definition at line 2065 of file formatting.c.

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

2066 {
2067  char *result;
2068  char *p;
2069 
2070  if (!buff)
2071  return NULL;
2072 
2073  result = pnstrdup(buff, nbytes);
2074 
2075  for (p = result; *p; p++)
2076  *p = pg_ascii_toupper((unsigned char) *p);
2077 
2078  return result;
2079 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
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 2143 of file formatting.c.

References asc_toupper().

Referenced by DCH_to_char().

2144 {
2145  return asc_toupper(buff, strlen(buff));
2146 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2065

◆ datetime_to_char_body()

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

Definition at line 3874 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().

3875 {
3876  FormatNode *format;
3877  char *fmt_str,
3878  *result;
3879  bool incache;
3880  int fmt_len;
3881  text *res;
3882 
3883  /*
3884  * Convert fmt to C string
3885  */
3886  fmt_str = text_to_cstring(fmt);
3887  fmt_len = strlen(fmt_str);
3888 
3889  /*
3890  * Allocate workspace for result as C string
3891  */
3892  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
3893  *result = '\0';
3894 
3895  if (fmt_len > DCH_CACHE_SIZE)
3896  {
3897  /*
3898  * Allocate new memory if format picture is bigger than static cache
3899  * and do not use cache (call parser always)
3900  */
3901  incache = false;
3902 
3903  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3904 
3905  parse_format(format, fmt_str, DCH_keywords,
3906  DCH_suff, DCH_index, DCH_FLAG, NULL);
3907  }
3908  else
3909  {
3910  /*
3911  * Use cache buffers
3912  */
3913  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
3914 
3915  incache = true;
3916  format = ent->format;
3917  }
3918 
3919  /* The real work is here */
3920  DCH_to_char(format, is_interval, tmtc, result, collid);
3921 
3922  if (!incache)
3923  pfree(format);
3924 
3925  pfree(fmt_str);
3926 
3927  /* convert C-string result to TEXT format */
3928  res = cstring_to_text(result);
3929 
3930  pfree(result);
3931  return res;
3932 }
static const KeySuffix DCH_suff[]
Definition: formatting.c:581
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:955
void pfree(void *pointer)
Definition: mcxt.c:1056
#define DCH_CACHE_SIZE
Definition: formatting.c:413
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
Definition: formatting.c:2573
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:423
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:1332
#define DCH_FLAG
Definition: formatting.c:142
text * cstring_to_text(const char *s)
Definition: varlena.c:171
char * text_to_cstring(const text *t)
Definition: varlena.c:204
void * palloc(Size size)
Definition: mcxt.c:949
static const KeyWord DCH_keywords[]
Definition: formatting.c:785
Definition: c.h:549
static char format
Definition: pg_basebackup.c:85
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:157
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:3847

◆ DCH_cache_fetch()

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

Definition at line 3847 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().

3848 {
3849  DCHCacheEntry *ent;
3850 
3851  if ((ent = DCH_cache_search(str, std)) == NULL)
3852  {
3853  /*
3854  * Not in the cache, must run parser and save a new format-picture to
3855  * the cache. Do not mark the cache entry valid until parsing
3856  * succeeds.
3857  */
3858  ent = DCH_cache_getnew(str, std);
3859 
3861  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
3862 
3863  ent->valid = true;
3864  }
3865  return ent;
3866 }
static DCHCacheEntry * DCH_cache_getnew(const char *str, bool std)
Definition: formatting.c:3766
static const KeySuffix DCH_suff[]
Definition: formatting.c:581
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:955
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:423
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:1332
static DCHCacheEntry * DCH_cache_search(const char *str, bool std)
Definition: formatting.c:3826
#define DCH_FLAG
Definition: formatting.c:142
static const KeyWord DCH_keywords[]
Definition: formatting.c:785
#define STD_FLAG
Definition: formatting.c:144

◆ DCH_cache_getnew()

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

Definition at line 3766 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, StrNCpy, TopMemoryContext, and DCHCacheEntry::valid.

Referenced by DCH_cache_fetch().

3767 {
3768  DCHCacheEntry *ent;
3769 
3770  /* Ensure we can advance DCHCounter below */
3772 
3773  /*
3774  * If cache is full, remove oldest entry (or recycle first not-valid one)
3775  */
3777  {
3778  DCHCacheEntry *old = DCHCache[0];
3779 
3780 #ifdef DEBUG_TO_FROM_CHAR
3781  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3782 #endif
3783  if (old->valid)
3784  {
3785  for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
3786  {
3787  ent = DCHCache[i];
3788  if (!ent->valid)
3789  {
3790  old = ent;
3791  break;
3792  }
3793  if (ent->age < old->age)
3794  old = ent;
3795  }
3796  }
3797 #ifdef DEBUG_TO_FROM_CHAR
3798  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3799 #endif
3800  old->valid = false;
3801  StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
3802  old->age = (++DCHCounter);
3803  /* caller is expected to fill format, then set valid */
3804  return old;
3805  }
3806  else
3807  {
3808 #ifdef DEBUG_TO_FROM_CHAR
3809  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3810 #endif
3811  Assert(DCHCache[n_DCHCache] == NULL);
3812  DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
3814  ent->valid = false;
3815  StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
3816  ent->std = std;
3817  ent->age = (++DCHCounter);
3818  /* caller is expected to fill format, then set valid */
3819  ++n_DCHCache;
3820  return ent;
3821  }
3822 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:424
#define DCH_CACHE_SIZE
Definition: formatting.c:413
static int n_DCHCache
Definition: formatting.c:441
MemoryContext TopMemoryContext
Definition: mcxt.c:44
#define DCH_CACHE_ENTRIES
Definition: formatting.c:418
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define Assert(condition)
Definition: c.h:732
#define StrNCpy(dst, src, len)
Definition: c.h:928
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3646
#define elog(elevel,...)
Definition: elog.h:226
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:440
static int DCHCounter
Definition: formatting.c:442

◆ DCH_cache_search()

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

Definition at line 3826 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().

3827 {
3828  /* Ensure we can advance DCHCounter below */
3830 
3831  for (int i = 0; i < n_DCHCache; i++)
3832  {
3833  DCHCacheEntry *ent = DCHCache[i];
3834 
3835  if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
3836  {
3837  ent->age = (++DCHCounter);
3838  return ent;
3839  }
3840  }
3841 
3842  return NULL;
3843 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:424
static int n_DCHCache
Definition: formatting.c:441
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3646
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:440
static int DCHCounter
Definition: formatting.c:442

◆ DCH_datetime_type()

static int DCH_datetime_type ( FormatNode node,
bool have_error 
)
static

Definition at line 3662 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().

3663 {
3664  FormatNode *n;
3665  int flags = 0;
3666 
3667  for (n = node; n->type != NODE_TYPE_END; n++)
3668  {
3669  if (n->type != NODE_TYPE_ACTION)
3670  continue;
3671 
3672  switch (n->key->id)
3673  {
3674  case DCH_FX:
3675  break;
3676  case DCH_A_M:
3677  case DCH_P_M:
3678  case DCH_a_m:
3679  case DCH_p_m:
3680  case DCH_AM:
3681  case DCH_PM:
3682  case DCH_am:
3683  case DCH_pm:
3684  case DCH_HH:
3685  case DCH_HH12:
3686  case DCH_HH24:
3687  case DCH_MI:
3688  case DCH_SS:
3689  case DCH_MS: /* millisecond */
3690  case DCH_US: /* microsecond */
3691  case DCH_FF1:
3692  case DCH_FF2:
3693  case DCH_FF3:
3694  case DCH_FF4:
3695  case DCH_FF5:
3696  case DCH_FF6:
3697  case DCH_SSSS:
3698  flags |= DCH_TIMED;
3699  break;
3700  case DCH_tz:
3701  case DCH_TZ:
3702  case DCH_OF:
3704  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3705  errmsg("formatting field \"%s\" is only supported in to_char",
3706  n->key->name))));
3707  flags |= DCH_ZONED;
3708  break;
3709  case DCH_TZH:
3710  case DCH_TZM:
3711  flags |= DCH_ZONED;
3712  break;
3713  case DCH_A_D:
3714  case DCH_B_C:
3715  case DCH_a_d:
3716  case DCH_b_c:
3717  case DCH_AD:
3718  case DCH_BC:
3719  case DCH_ad:
3720  case DCH_bc:
3721  case DCH_MONTH:
3722  case DCH_Month:
3723  case DCH_month:
3724  case DCH_MON:
3725  case DCH_Mon:
3726  case DCH_mon:
3727  case DCH_MM:
3728  case DCH_DAY:
3729  case DCH_Day:
3730  case DCH_day:
3731  case DCH_DY:
3732  case DCH_Dy:
3733  case DCH_dy:
3734  case DCH_DDD:
3735  case DCH_IDDD:
3736  case DCH_DD:
3737  case DCH_D:
3738  case DCH_ID:
3739  case DCH_WW:
3740  case DCH_Q:
3741  case DCH_CC:
3742  case DCH_Y_YYY:
3743  case DCH_YYYY:
3744  case DCH_IYYY:
3745  case DCH_YYY:
3746  case DCH_IYY:
3747  case DCH_YY:
3748  case DCH_IY:
3749  case DCH_Y:
3750  case DCH_I:
3751  case DCH_RM:
3752  case DCH_rm:
3753  case DCH_W:
3754  case DCH_J:
3755  flags |= DCH_DATED;
3756  break;
3757  }
3758  }
3759 
3760 on_error:
3761  return flags;
3762 }
#define NODE_TYPE_END
Definition: formatting.c:204
uint8 type
Definition: formatting.c:198
const KeyWord * key
Definition: formatting.c:201
int errcode(int sqlerrcode)
Definition: elog.c:570
int id
Definition: formatting.c:191
#define DCH_TIMED
Definition: formatting.c:1034
#define DCH_DATED
Definition: formatting.c:1033
#define NODE_TYPE_ACTION
Definition: formatting.c:205
#define ERROR
Definition: elog.h:43
#define DCH_ZONED
Definition: formatting.c:1035
#define ereport(elevel, rest)
Definition: elog.h:141
const char * name
Definition: formatting.c:189
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define RETURN_ERROR(throw_error)
Definition: formatting.c:119

◆ DCH_from_char()

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

Definition at line 3169 of file formatting.c.

References adbc_strings, adbc_strings_long, adjust_partial_year_to_2020(), ALL_LOWER, ALL_UPPER, ampm_strings, ampm_strings_long, Assert, TmFromChar::bc, TmFromChar::cc, FormatNode::character, CHECK_ERROR, TmFromChar::clock, CLOCK_12_HOUR, TmFromChar::d, KeyWord::date_mode, days, 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, is_separator_char(), TmFromChar::j, FormatNode::key, KeyWord::len, MAX_DAY_LEN, MAX_DY_LEN, MAX_MON_LEN, MAX_MONTH_LEN, MAX_RM_LEN, TmFromChar::mi, TmFromChar::mm, months, months_full, MONTHS_PER_YEAR, TmFromChar::ms, KeyWord::name, NODE_TYPE_ACTION, NODE_TYPE_END, NODE_TYPE_SEPARATOR, NODE_TYPE_SPACE, ONE_UPPER, pg_mblen(), TmFromChar::pm, RETURN_ERROR, rm_months_lower, rm_months_upper, 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().

3171 {
3172  FormatNode *n;
3173  char *s;
3174  int len,
3175  value;
3176  bool fx_mode = std;
3177 
3178  /* number of extra skipped characters (more than given in format string) */
3179  int extra_skip = 0;
3180 
3181  for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
3182  {
3183  /*
3184  * Ignore spaces at the beginning of the string and before fields when
3185  * not in FX (fixed width) mode.
3186  */
3187  if (!fx_mode && (n->type != NODE_TYPE_ACTION || n->key->id != DCH_FX) &&
3188  (n->type == NODE_TYPE_ACTION || n == node))
3189  {
3190  while (*s != '\0' && isspace((unsigned char) *s))
3191  {
3192  s++;
3193  extra_skip++;
3194  }
3195  }
3196 
3197  if (n->type == NODE_TYPE_SPACE || n->type == NODE_TYPE_SEPARATOR)
3198  {
3199  if (std)
3200  {
3201  /*
3202  * Standard mode requires strict matching between format
3203  * string separators/spaces and input string.
3204  */
3205  Assert(n->character[0] && !n->character[1]);
3206 
3207  if (*s == n->character[0])
3208  s++;
3209  else
3211  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3212  errmsg("unmatched format separator \"%c\"",
3213  n->character[0]))));
3214  }
3215  else if (!fx_mode)
3216  {
3217  /*
3218  * In non FX (fixed format) mode one format string space or
3219  * separator match to one space or separator in input string.
3220  * Or match nothing if there is no space or separator in the
3221  * current position of input string.
3222  */
3223  extra_skip--;
3224  if (isspace((unsigned char) *s) || is_separator_char(s))
3225  {
3226  s++;
3227  extra_skip++;
3228  }
3229  }
3230  else
3231  {
3232  /*
3233  * In FX mode, on format string space or separator we consume
3234  * exactly one character from input string. Notice we don't
3235  * insist that the consumed character match the format's
3236  * character.
3237  */
3238  s += pg_mblen(s);
3239  }
3240  continue;
3241  }
3242  else if (n->type != NODE_TYPE_ACTION)
3243  {
3244  /*
3245  * Text character, so consume one character from input string.
3246  * Notice we don't insist that the consumed character match the
3247  * format's character.
3248  */
3249  if (!fx_mode)
3250  {
3251  /*
3252  * In non FX mode we might have skipped some extra characters
3253  * (more than specified in format string) before. In this
3254  * case we don't skip input string character, because it might
3255  * be part of field.
3256  */
3257  if (extra_skip > 0)
3258  extra_skip--;
3259  else
3260  s += pg_mblen(s);
3261  }
3262  else
3263  {
3264  s += pg_mblen(s);
3265  }
3266  continue;
3267  }
3268 
3269  from_char_set_mode(out, n->key->date_mode, have_error);
3270  CHECK_ERROR;
3271 
3272  switch (n->key->id)
3273  {
3274  case DCH_FX:
3275  fx_mode = true;
3276  break;
3277  case DCH_A_M:
3278  case DCH_P_M:
3279  case DCH_a_m:
3280  case DCH_p_m:
3282  ALL_UPPER, n->key->len, n, have_error);
3283  CHECK_ERROR;
3284  from_char_set_int(&out->pm, value % 2, n, have_error);
3285  CHECK_ERROR;
3286  out->clock = CLOCK_12_HOUR;
3287  break;
3288  case DCH_AM:
3289  case DCH_PM:
3290  case DCH_am:
3291  case DCH_pm:
3292  from_char_seq_search(&value, &s, ampm_strings,
3293  ALL_UPPER, n->key->len, n, have_error);
3294  CHECK_ERROR;
3295  from_char_set_int(&out->pm, value % 2, n, have_error);
3296  CHECK_ERROR;
3297  out->clock = CLOCK_12_HOUR;
3298  break;
3299  case DCH_HH:
3300  case DCH_HH12:
3301  from_char_parse_int_len(&out->hh, &s, 2, n, have_error);
3302  CHECK_ERROR;
3303  out->clock = CLOCK_12_HOUR;
3304  SKIP_THth(s, n->suffix);
3305  break;
3306  case DCH_HH24:
3307  from_char_parse_int_len(&out->hh, &s, 2, n, have_error);
3308  CHECK_ERROR;
3309  SKIP_THth(s, n->suffix);
3310  break;
3311  case DCH_MI:
3312  from_char_parse_int(&out->mi, &s, n, have_error);
3313  CHECK_ERROR;
3314  SKIP_THth(s, n->suffix);
3315  break;
3316  case DCH_SS:
3317  from_char_parse_int(&out->ss, &s, n, have_error);
3318  CHECK_ERROR;
3319  SKIP_THth(s, n->suffix);
3320  break;
3321  case DCH_MS: /* millisecond */
3322  len = from_char_parse_int_len(&out->ms, &s, 3, n, have_error);
3323  CHECK_ERROR;
3324 
3325  /*
3326  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
3327  */
3328  out->ms *= len == 1 ? 100 :
3329  len == 2 ? 10 : 1;
3330 
3331  SKIP_THth(s, n->suffix);
3332  break;
3333  case DCH_FF1:
3334  case DCH_FF2:
3335  case DCH_FF3:
3336  case DCH_FF4:
3337  case DCH_FF5:
3338  case DCH_FF6:
3339  out->ff = n->key->id - DCH_FF1 + 1;
3340  /* fall through */
3341  case DCH_US: /* microsecond */
3342  len = from_char_parse_int_len(&out->us, &s,
3343  n->key->id == DCH_US ? 6 :
3344  out->ff, n, have_error);
3345  CHECK_ERROR;
3346 
3347  out->us *= len == 1 ? 100000 :
3348  len == 2 ? 10000 :
3349  len == 3 ? 1000 :
3350  len == 4 ? 100 :
3351  len == 5 ? 10 : 1;
3352 
3353  SKIP_THth(s, n->suffix);
3354  break;
3355  case DCH_SSSS:
3356  from_char_parse_int(&out->ssss, &s, n, have_error);
3357  CHECK_ERROR;
3358  SKIP_THth(s, n->suffix);
3359  break;
3360  case DCH_tz:
3361  case DCH_TZ:
3362  case DCH_OF:
3364  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3365  errmsg("formatting field \"%s\" is only supported in to_char",
3366  n->key->name))));
3367  CHECK_ERROR;
3368  break;
3369  case DCH_TZH:
3370 
3371  /*
3372  * Value of TZH might be negative. And the issue is that we
3373  * might swallow minus sign as the separator. So, if we have
3374  * skipped more characters than specified in the format
3375  * string, then we consider prepending last skipped minus to
3376  * TZH.
3377  */
3378  if (*s == '+' || *s == '-' || *s == ' ')
3379  {
3380  out->tzsign = *s == '-' ? -1 : +1;
3381  s++;
3382  }
3383  else
3384  {
3385  if (extra_skip > 0 && *(s - 1) == '-')
3386  out->tzsign = -1;
3387  else
3388  out->tzsign = +1;
3389  }
3390 
3391  from_char_parse_int_len(&out->tzh, &s, 2, n, have_error);
3392  CHECK_ERROR;
3393  break;
3394  case DCH_TZM:
3395  /* assign positive timezone sign if TZH was not seen before */
3396  if (!out->tzsign)
3397  out->tzsign = +1;
3398  from_char_parse_int_len(&out->tzm, &s, 2, n, have_error);
3399  CHECK_ERROR;
3400  break;
3401  case DCH_A_D:
3402  case DCH_B_C:
3403  case DCH_a_d:
3404  case DCH_b_c:
3406  ALL_UPPER, n->key->len, n, have_error);
3407  CHECK_ERROR;
3408  from_char_set_int(&out->bc, value % 2, n, have_error);
3409  CHECK_ERROR;
3410  break;
3411  case DCH_AD:
3412  case DCH_BC:
3413  case DCH_ad:
3414  case DCH_bc:
3415  from_char_seq_search(&value, &s, adbc_strings,
3416  ALL_UPPER, n->key->len, n, have_error);
3417  CHECK_ERROR;
3418  from_char_set_int(&out->bc, value % 2, n, have_error);
3419  CHECK_ERROR;
3420  break;
3421  case DCH_MONTH:
3422  case DCH_Month:
3423  case DCH_month:
3425  MAX_MONTH_LEN, n, have_error);
3426  CHECK_ERROR;
3427  from_char_set_int(&out->mm, value + 1, n, have_error);
3428  CHECK_ERROR;
3429  break;
3430  case DCH_MON:
3431  case DCH_Mon:
3432  case DCH_mon:
3433  from_char_seq_search(&value, &s, months, ONE_UPPER,
3434  MAX_MON_LEN, n, have_error);
3435  CHECK_ERROR;
3436  from_char_set_int(&out->mm, value + 1, n, have_error);
3437  CHECK_ERROR;
3438  break;
3439  case DCH_MM:
3440  from_char_parse_int(&out->mm, &s, n, have_error);
3441  CHECK_ERROR;
3442  SKIP_THth(s, n->suffix);
3443  break;
3444  case DCH_DAY:
3445  case DCH_Day:
3446  case DCH_day:
3447  from_char_seq_search(&value, &s, days, ONE_UPPER,
3448  MAX_DAY_LEN, n, have_error);
3449  CHECK_ERROR;
3450  from_char_set_int(&out->d, value, n, have_error);
3451  CHECK_ERROR;
3452  out->d++;
3453  break;
3454  case DCH_DY:
3455  case DCH_Dy:
3456  case DCH_dy:
3457  from_char_seq_search(&value, &s, days, ONE_UPPER,
3458  MAX_DY_LEN, n, have_error);
3459  CHECK_ERROR;
3460  from_char_set_int(&out->d, value, n, have_error);
3461  CHECK_ERROR;
3462  out->d++;
3463  break;
3464  case DCH_DDD:
3465  from_char_parse_int(&out->ddd, &s, n, have_error);
3466  CHECK_ERROR;
3467  SKIP_THth(s, n->suffix);
3468  break;
3469  case DCH_IDDD:
3470  from_char_parse_int_len(&out->ddd, &s, 3, n, have_error);
3471  CHECK_ERROR;
3472  SKIP_THth(s, n->suffix);
3473  break;
3474  case DCH_DD:
3475  from_char_parse_int(&out->dd, &s, n, have_error);
3476  CHECK_ERROR;
3477  SKIP_THth(s, n->suffix);
3478  break;
3479  case DCH_D:
3480  from_char_parse_int(&out->d, &s, n, have_error);
3481  CHECK_ERROR;
3482  SKIP_THth(s, n->suffix);
3483  break;
3484  case DCH_ID:
3485  from_char_parse_int_len(&out->d, &s, 1, n, have_error);
3486  CHECK_ERROR;
3487  /* Shift numbering to match Gregorian where Sunday = 1 */
3488  if (++out->d > 7)
3489  out->d = 1;
3490  SKIP_THth(s, n->suffix);
3491  break;
3492  case DCH_WW:
3493  case DCH_IW:
3494  from_char_parse_int(&out->ww, &s, n, have_error);
3495  CHECK_ERROR;
3496  SKIP_THth(s, n->suffix);
3497  break;
3498  case DCH_Q:
3499 
3500  /*
3501  * We ignore 'Q' when converting to date because it is unclear
3502  * which date in the quarter to use, and some people specify
3503  * both quarter and month, so if it was honored it might
3504  * conflict with the supplied month. That is also why we don't
3505  * throw an error.
3506  *
3507  * We still parse the source string for an integer, but it
3508  * isn't stored anywhere in 'out'.
3509  */
3510  from_char_parse_int((int *) NULL, &s, n, have_error);
3511  CHECK_ERROR;
3512  SKIP_THth(s, n->suffix);
3513  break;
3514  case DCH_CC:
3515  from_char_parse_int(&out->cc, &s, n, have_error);
3516  CHECK_ERROR;
3517  SKIP_THth(s, n->suffix);
3518  break;
3519  case DCH_Y_YYY:
3520  {
3521  int matched,
3522  years,
3523  millennia,
3524  nch;
3525 
3526  matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3527  if (matched < 2)
3529  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3530  errmsg("invalid input string for \"Y,YYY\""))));
3531  years += (millennia * 1000);
3532  from_char_set_int(&out->year, years, n, have_error);
3533  CHECK_ERROR;
3534  out->yysz = 4;
3535  s += nch;
3536  SKIP_THth(s, n->suffix);
3537  }
3538  break;
3539  case DCH_YYYY:
3540  case DCH_IYYY:
3541  from_char_parse_int(&out->year, &s, n, have_error);
3542  CHECK_ERROR;
3543  out->yysz = 4;
3544  SKIP_THth(s, n->suffix);
3545  break;
3546  case DCH_YYY:
3547  case DCH_IYY:
3548  len = from_char_parse_int(&out->year, &s, n, have_error);
3549  CHECK_ERROR;
3550  if (len < 4)
3551  out->year = adjust_partial_year_to_2020(out->year);
3552  out->yysz = 3;
3553  SKIP_THth(s, n->suffix);
3554  break;
3555  case DCH_YY:
3556  case DCH_IY:
3557  len = from_char_parse_int(&out->year, &s, n, have_error);
3558  CHECK_ERROR;
3559  if (len < 4)
3560  out->year = adjust_partial_year_to_2020(out->year);
3561  out->yysz = 2;
3562  SKIP_THth(s, n->suffix);
3563  break;
3564  case DCH_Y:
3565  case DCH_I:
3566  len = from_char_parse_int(&out->year, &s, n, have_error);
3567  CHECK_ERROR;
3568  if (len < 4)
3569  out->year = adjust_partial_year_to_2020(out->year);
3570  out->yysz = 1;
3571  SKIP_THth(s, n->suffix);
3572  break;
3573  case DCH_RM:
3575  ALL_UPPER, MAX_RM_LEN, n, have_error);
3576  CHECK_ERROR;
3577  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value,
3578  n, have_error);
3579  CHECK_ERROR;
3580  break;
3581  case DCH_rm:
3583  ALL_LOWER, MAX_RM_LEN, n, have_error);
3584  CHECK_ERROR;
3585  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value,
3586  n, have_error);
3587  CHECK_ERROR;
3588  break;
3589  case DCH_W:
3590  from_char_parse_int(&out->w, &s, n, have_error);
3591  CHECK_ERROR;
3592  SKIP_THth(s, n->suffix);
3593  break;
3594  case DCH_J:
3595  from_char_parse_int(&out->j, &s, n, have_error);
3596  CHECK_ERROR;
3597  SKIP_THth(s, n->suffix);
3598  break;
3599  }
3600 
3601  /* Ignore all spaces after fields */
3602  if (!fx_mode)
3603  {
3604  extra_skip = 0;
3605  while (*s != '\0' && isspace((unsigned char) *s))
3606  {
3607  s++;
3608  extra_skip++;
3609  }
3610  }
3611  }
3612 
3613  /*
3614  * Standard parsing mode doesn't allow unmatched format patterns or
3615  * trailing characters in the input string.
3616  */
3617  if (std)
3618  {
3619  if (n->type != NODE_TYPE_END)
3621  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3622  errmsg("input string is too short for datetime format"))));
3623 
3624  while (*s != '\0' && isspace((unsigned char) *s))
3625  s++;
3626 
3627  if (*s != '\0')
3629  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3630  errmsg("trailing characters remain in input string "
3631  "after datetime format"))));
3632  }
3633 
3634 on_error:
3635  return;
3636 }
static int from_char_seq_search(int *dest, char **src, const char *const *array, int type, int max, FormatNode *node, bool *have_error)
Definition: formatting.c:2540
#define NODE_TYPE_END
Definition: formatting.c:204
uint8 type
Definition: formatting.c:198
const KeyWord * key
Definition: formatting.c:201
static const char *const adbc_strings_long[]
Definition: formatting.c:260
FromCharDateMode date_mode
Definition: formatting.c:193
#define MAX_DY_LEN
Definition: formatting.c:327
static struct @145 value
int errcode(int sqlerrcode)
Definition: elog.c:570
static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode, bool *have_error)
Definition: formatting.c:2283
static const char *const rm_months_upper[]
Definition: formatting.c:295
static int from_char_parse_int(int *dest, char **src, FormatNode *node, bool *have_error)
Definition: formatting.c:2451
int id
Definition: formatting.c:191
static const char *const ampm_strings_long[]
Definition: formatting.c:287
#define CHECK_ERROR
Definition: formatting.c:132
static const char *const adbc_strings[]
Definition: formatting.c:259
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define MAX_MON_LEN
Definition: formatting.c:325
#define ONE_UPPER
Definition: formatting.c:320
const char *const months[]
Definition: datetime.c:66
#define NODE_TYPE_ACTION
Definition: formatting.c:205
#define ERROR
Definition: elog.h:43
char character[MAX_MULTIBYTE_CHAR_LEN+1]
Definition: formatting.c:199
#define SKIP_THth(ptr, _suf)
Definition: formatting.c:2157
static bool is_separator_char(const char *str)
Definition: formatting.c:1143
#define NODE_TYPE_SPACE
Definition: formatting.c:208
const char *const days[]
Definition: datetime.c:69
#define NODE_TYPE_SEPARATOR
Definition: formatting.c:207
#define ereport(elevel, rest)
Definition: elog.h:141
#define MAX_RM_LEN
Definition: formatting.c:328
#define CLOCK_12_HOUR
Definition: formatting.c:214
static const char *const ampm_strings[]
Definition: formatting.c:286
const char * name
Definition: formatting.c:189
static const char *const months_full[]
Definition: formatting.c:221
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node, bool *have_error)
Definition: formatting.c:2351
int len
Definition: formatting.c:190
#define ALL_UPPER
Definition: formatting.c:321
static int adjust_partial_year_to_2020(int year)
Definition: formatting.c:2238
#define Assert(condition)
Definition: c.h:732
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802
uint8 suffix
Definition: formatting.c:200
#define MAX_MONTH_LEN
Definition: formatting.c:324
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define ALL_LOWER
Definition: formatting.c:322
#define MAX_DAY_LEN
Definition: formatting.c:326
static void from_char_set_int(int *dest, const int value, const FormatNode *node, bool *have_error)
Definition: formatting.c:2310
static const char *const rm_months_lower[]
Definition: formatting.c:298
#define RETURN_ERROR(throw_error)
Definition: formatting.c:119

◆ DCH_prevent_counter_overflow()

static void DCH_prevent_counter_overflow ( void  )
inlinestatic

Definition at line 3646 of file formatting.c.

References DCHCounter, i, and n_DCHCache.

Referenced by DCH_cache_getnew(), and DCH_cache_search().

3647 {
3648  if (DCHCounter >= (INT_MAX - 1))
3649  {
3650  for (int i = 0; i < n_DCHCache; i++)
3651  DCHCache[i]->age >>= 1;
3652  DCHCounter >>= 1;
3653  }
3654 }
static int n_DCHCache
Definition: formatting.c:441
int i
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:440
static int DCHCounter
Definition: formatting.c:442

◆ DCH_to_char()

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

Definition at line 2573 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().

2574 {
2575  FormatNode *n;
2576  char *s;
2577  struct pg_tm *tm = &in->tm;
2578  int i;
2579 
2580  /* cache localized days and months */
2582 
2583  s = out;
2584  for (n = node; n->type != NODE_TYPE_END; n++)
2585  {
2586  if (n->type != NODE_TYPE_ACTION)
2587  {
2588  strcpy(s, n->character);
2589  s += strlen(s);
2590  continue;
2591  }
2592 
2593  switch (n->key->id)
2594  {
2595  case DCH_A_M:
2596  case DCH_P_M:
2597  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2598  ? P_M_STR : A_M_STR);
2599  s += strlen(s);
2600  break;
2601  case DCH_AM:
2602  case DCH_PM:
2603  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2604  ? PM_STR : AM_STR);
2605  s += strlen(s);
2606  break;
2607  case DCH_a_m:
2608  case DCH_p_m:
2609  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2610  ? p_m_STR : a_m_STR);
2611  s += strlen(s);
2612  break;
2613  case DCH_am:
2614  case DCH_pm:
2615  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2616  ? pm_STR : am_STR);
2617  s += strlen(s);
2618  break;
2619  case DCH_HH:
2620  case DCH_HH12:
2621 
2622  /*
2623  * display time as shown on a 12-hour clock, even for
2624  * intervals
2625  */
2626  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2627  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? HOURS_PER_DAY / 2 :
2628  tm->tm_hour % (HOURS_PER_DAY / 2));
2629  if (S_THth(n->suffix))
2630  str_numth(s, s, S_TH_TYPE(n->suffix));
2631  s += strlen(s);
2632  break;
2633  case DCH_HH24:
2634  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2635  tm->tm_hour);
2636  if (S_THth(n->suffix))
2637  str_numth(s, s, S_TH_TYPE(n->suffix));
2638  s += strlen(s);
2639  break;
2640  case DCH_MI:
2641  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2642  tm->tm_min);
2643  if (S_THth(n->suffix))
2644  str_numth(s, s, S_TH_TYPE(n->suffix));
2645  s += strlen(s);
2646  break;
2647  case DCH_SS:
2648  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2649  tm->tm_sec);
2650  if (S_THth(n->suffix))
2651  str_numth(s, s, S_TH_TYPE(n->suffix));
2652  s += strlen(s);
2653  break;
2654 #define DCH_to_char_fsec(frac_fmt, frac_val) \
2655  sprintf(s, frac_fmt, (int) (frac_val)); \
2656  if (S_THth(n->suffix)) \
2657  str_numth(s, s, S_TH_TYPE(n->suffix)); \
2658  s += strlen(s);
2659  case DCH_FF1: /* tenth of second */
2660  DCH_to_char_fsec("%01d", in->fsec / 100000);
2661  break;
2662  case DCH_FF2: /* hundredth of second */
2663  DCH_to_char_fsec("%02d", in->fsec / 10000);
2664  break;
2665  case DCH_FF3:
2666  case DCH_MS: /* millisecond */
2667  DCH_to_char_fsec("%03d", in->fsec / 1000);
2668  break;
2669  case DCH_FF4: /* tenth of a millisecond */
2670  DCH_to_char_fsec("%04d", in->fsec / 100);
2671  break;
2672  case DCH_FF5: /* hundredth of a millisecond */
2673  DCH_to_char_fsec("%05d", in->fsec / 10);
2674  break;
2675  case DCH_FF6:
2676  case DCH_US: /* microsecond */
2677  DCH_to_char_fsec("%06d", in->fsec);
2678  break;
2679 #undef DCH_to_char_fsec
2680  case DCH_SSSS:
2681  sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2682  tm->tm_min * SECS_PER_MINUTE +
2683  tm->tm_sec);
2684  if (S_THth(n->suffix))
2685  str_numth(s, s, S_TH_TYPE(n->suffix));
2686  s += strlen(s);
2687  break;
2688  case DCH_tz:
2690  if (tmtcTzn(in))
2691  {
2692  /* We assume here that timezone names aren't localized */
2693  char *p = asc_tolower_z(tmtcTzn(in));
2694 
2695  strcpy(s, p);
2696  pfree(p);
2697  s += strlen(s);
2698  }
2699  break;
2700  case DCH_TZ:
2702  if (tmtcTzn(in))
2703  {
2704  strcpy(s, tmtcTzn(in));
2705  s += strlen(s);
2706  }
2707  break;
2708  case DCH_TZH:
2710  sprintf(s, "%c%02d",
2711  (tm->tm_gmtoff >= 0) ? '+' : '-',
2712  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2713  s += strlen(s);
2714  break;
2715  case DCH_TZM:
2717  sprintf(s, "%02d",
2718  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2719  s += strlen(s);
2720  break;
2721  case DCH_OF:
2723  sprintf(s, "%c%0*d",
2724  (tm->tm_gmtoff >= 0) ? '+' : '-',
2725  S_FM(n->suffix) ? 0 : 2,
2726  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2727  s += strlen(s);
2728  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2729  {
2730  sprintf(s, ":%02d",
2731  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2732  s += strlen(s);
2733  }
2734  break;
2735  case DCH_A_D:
2736  case DCH_B_C:
2738  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2739  s += strlen(s);
2740  break;
2741  case DCH_AD:
2742  case DCH_BC:
2744  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2745  s += strlen(s);
2746  break;
2747  case DCH_a_d:
2748  case DCH_b_c:
2750  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2751  s += strlen(s);
2752  break;
2753  case DCH_ad:
2754  case DCH_bc:
2756  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2757  s += strlen(s);
2758  break;
2759  case DCH_MONTH:
2761  if (!tm->tm_mon)
2762  break;
2763  if (S_TM(n->suffix))
2764  {
2765  char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2766 
2767  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2768  strcpy(s, str);
2769  else
2770  ereport(ERROR,
2771  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2772  errmsg("localized string format value too long")));
2773  }
2774  else
2775  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2776  asc_toupper_z(months_full[tm->tm_mon - 1]));
2777  s += strlen(s);
2778  break;
2779  case DCH_Month:
2781  if (!tm->tm_mon)
2782  break;
2783  if (S_TM(n->suffix))
2784  {
2785  char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2786 
2787  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2788  strcpy(s, str);
2789  else
2790  ereport(ERROR,
2791  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2792  errmsg("localized string format value too long")));
2793  }
2794  else
2795  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2796  months_full[tm->tm_mon - 1]);
2797  s += strlen(s);
2798  break;
2799  case DCH_month:
2801  if (!tm->tm_mon)
2802  break;
2803  if (S_TM(n->suffix))
2804  {
2805  char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2806 
2807  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2808  strcpy(s, str);
2809  else
2810  ereport(ERROR,
2811  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2812  errmsg("localized string format value too long")));
2813  }
2814  else
2815  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2816  asc_tolower_z(months_full[tm->tm_mon - 1]));
2817  s += strlen(s);
2818  break;
2819  case DCH_MON:
2821  if (!tm->tm_mon)
2822  break;
2823  if (S_TM(n->suffix))
2824  {
2825  char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2826 
2827  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2828  strcpy(s, str);
2829  else
2830  ereport(ERROR,
2831  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2832  errmsg("localized string format value too long")));
2833  }
2834  else
2835  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2836  s += strlen(s);
2837  break;
2838  case DCH_Mon:
2840  if (!tm->tm_mon)
2841  break;
2842  if (S_TM(n->suffix))
2843  {
2844  char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2845 
2846  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2847  strcpy(s, str);
2848  else
2849  ereport(ERROR,
2850  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2851  errmsg("localized string format value too long")));
2852  }
2853  else
2854  strcpy(s, months[tm->tm_mon - 1]);
2855  s += strlen(s);
2856  break;
2857  case DCH_mon:
2859  if (!tm->tm_mon)
2860  break;
2861  if (S_TM(n->suffix))
2862  {
2863  char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2864 
2865  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2866  strcpy(s, str);
2867  else
2868  ereport(ERROR,
2869  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2870  errmsg("localized string format value too long")));
2871  }
2872  else
2873  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2874  s += strlen(s);
2875  break;
2876  case DCH_MM:
2877  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2878  tm->tm_mon);
2879  if (S_THth(n->suffix))
2880  str_numth(s, s, S_TH_TYPE(n->suffix));
2881  s += strlen(s);
2882  break;
2883  case DCH_DAY:
2885  if (S_TM(n->suffix))
2886  {
2887  char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2888 
2889  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2890  strcpy(s, str);
2891  else
2892  ereport(ERROR,
2893  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2894  errmsg("localized string format value too long")));
2895  }
2896  else
2897  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2898  asc_toupper_z(days[tm->tm_wday]));
2899  s += strlen(s);
2900  break;
2901  case DCH_Day:
2903  if (S_TM(n->suffix))
2904  {
2905  char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2906 
2907  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2908  strcpy(s, str);
2909  else
2910  ereport(ERROR,
2911  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2912  errmsg("localized string format value too long")));
2913  }
2914  else
2915  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2916  days[tm->tm_wday]);
2917  s += strlen(s);
2918  break;
2919  case DCH_day:
2921  if (S_TM(n->suffix))
2922  {
2923  char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
2924 
2925  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2926  strcpy(s, str);
2927  else
2928  ereport(ERROR,
2929  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2930  errmsg("localized string format value too long")));
2931  }
2932  else
2933  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2934  asc_tolower_z(days[tm->tm_wday]));
2935  s += strlen(s);
2936  break;
2937  case DCH_DY:
2939  if (S_TM(n->suffix))
2940  {
2941  char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
2942 
2943  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2944  strcpy(s, str);
2945  else
2946  ereport(ERROR,
2947  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2948  errmsg("localized string format value too long")));
2949  }
2950  else
2951  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
2952  s += strlen(s);
2953  break;
2954  case DCH_Dy:
2956  if (S_TM(n->suffix))
2957  {
2958  char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
2959 
2960  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2961  strcpy(s, str);
2962  else
2963  ereport(ERROR,
2964  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2965  errmsg("localized string format value too long")));
2966  }
2967  else
2968  strcpy(s, days_short[tm->tm_wday]);
2969  s += strlen(s);
2970  break;
2971  case DCH_dy:
2973  if (S_TM(n->suffix))
2974  {
2975  char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
2976 
2977  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2978  strcpy(s, str);
2979  else
2980  ereport(ERROR,
2981  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2982  errmsg("localized string format value too long")));
2983  }
2984  else
2985  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
2986  s += strlen(s);
2987  break;
2988  case DCH_DDD:
2989  case DCH_IDDD:
2990  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
2991  (n->key->id == DCH_DDD) ?
2992  tm->tm_yday :
2993  date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
2994  if (S_THth(n->suffix))
2995  str_numth(s, s, S_TH_TYPE(n->suffix));
2996  s += strlen(s);
2997  break;
2998  case DCH_DD:
2999  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
3000  if (S_THth(n->suffix))
3001  str_numth(s, s, S_TH_TYPE(n->suffix));
3002  s += strlen(s);
3003  break;
3004  case DCH_D:
3006  sprintf(s, "%d", tm->tm_wday + 1);
3007  if (S_THth(n->suffix))
3008  str_numth(s, s, S_TH_TYPE(n->suffix));
3009  s += strlen(s);
3010  break;
3011  case DCH_ID:
3013  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
3014  if (S_THth(n->suffix))
3015  str_numth(s, s, S_TH_TYPE(n->suffix));
3016  s += strlen(s);
3017  break;
3018  case DCH_WW:
3019  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3020  (tm->tm_yday - 1) / 7 + 1);
3021  if (S_THth(n->suffix))
3022  str_numth(s, s, S_TH_TYPE(n->suffix));
3023  s += strlen(s);
3024  break;
3025  case DCH_IW:
3026  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3027  date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
3028  if (S_THth(n->suffix))
3029  str_numth(s, s, S_TH_TYPE(n->suffix));
3030  s += strlen(s);
3031  break;
3032  case DCH_Q:
3033  if (!tm->tm_mon)
3034  break;
3035  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
3036  if (S_THth(n->suffix))
3037  str_numth(s, s, S_TH_TYPE(n->suffix));
3038  s += strlen(s);
3039  break;
3040  case DCH_CC:
3041  if (is_interval) /* straight calculation */
3042  i = tm->tm_year / 100;
3043  else
3044  {
3045  if (tm->tm_year > 0)
3046  /* Century 20 == 1901 - 2000 */
3047  i = (tm->tm_year - 1) / 100 + 1;
3048  else
3049  /* Century 6BC == 600BC - 501BC */
3050  i = tm->tm_year / 100 - 1;
3051  }
3052  if (i <= 99 && i >= -99)
3053  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
3054  else
3055  sprintf(s, "%d", i);
3056  if (S_THth(n->suffix))
3057  str_numth(s, s, S_TH_TYPE(n->suffix));
3058  s += strlen(s);
3059  break;
3060  case DCH_Y_YYY:
3061  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
3062  sprintf(s, "%d,%03d", i,
3063  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
3064  if (S_THth(n->suffix))
3065  str_numth(s, s, S_TH_TYPE(n->suffix));
3066  s += strlen(s);
3067  break;
3068  case DCH_YYYY:
3069  case DCH_IYYY:
3070  sprintf(s, "%0*d",
3071  S_FM(n->suffix) ? 0 :
3072  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
3073  (n->key->id == DCH_YYYY ?
3074  ADJUST_YEAR(tm->tm_year, is_interval) :
3076  tm->tm_mon,
3077  tm->tm_mday),
3078  is_interval)));
3079  if (S_THth(n->suffix))
3080  str_numth(s, s, S_TH_TYPE(n->suffix));
3081  s += strlen(s);
3082  break;
3083  case DCH_YYY:
3084  case DCH_IYY:
3085  sprintf(s, "%0*d",
3086  S_FM(n->suffix) ? 0 :
3087  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
3088  (n->key->id == DCH_YYY ?
3089  ADJUST_YEAR(tm->tm_year, is_interval) :
3091  tm->tm_mon,
3092  tm->tm_mday),
3093  is_interval)) % 1000);
3094  if (S_THth(n->suffix))
3095  str_numth(s, s, S_TH_TYPE(n->suffix));
3096  s += strlen(s);
3097  break;
3098  case DCH_YY:
3099  case DCH_IY:
3100  sprintf(s, "%0*d",
3101  S_FM(n->suffix) ? 0 :
3102  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
3103  (n->key->id == DCH_YY ?
3104  ADJUST_YEAR(tm->tm_year, is_interval) :
3106  tm->tm_mon,
3107  tm->tm_mday),
3108  is_interval)) % 100);
3109  if (S_THth(n->suffix))
3110  str_numth(s, s, S_TH_TYPE(n->suffix));
3111  s += strlen(s);
3112  break;
3113  case DCH_Y:
3114  case DCH_I:
3115  sprintf(s, "%1d",
3116  (n->key->id == DCH_Y ?
3117  ADJUST_YEAR(tm->tm_year, is_interval) :
3119  tm->tm_mon,
3120  tm->tm_mday),
3121  is_interval)) % 10);
3122  if (S_THth(n->suffix))
3123  str_numth(s, s, S_TH_TYPE(n->suffix));
3124  s += strlen(s);
3125  break;
3126  case DCH_RM:
3127  if (!tm->tm_mon)
3128  break;
3129  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
3131  s += strlen(s);
3132  break;
3133  case DCH_rm:
3134  if (!tm->tm_mon)
3135  break;
3136  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
3138  s += strlen(s);
3139  break;
3140  case DCH_W:
3141  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
3142  if (S_THth(n->suffix))
3143  str_numth(s, s, S_TH_TYPE(n->suffix));
3144  s += strlen(s);
3145  break;
3146  case DCH_J:
3147  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
3148  if (S_THth(n->suffix))
3149  str_numth(s, s, S_TH_TYPE(n->suffix));
3150  s += strlen(s);
3151  break;
3152  }
3153  }
3154 
3155  *s = '\0';
3156 }
#define a_m_STR
Definition: formatting.c:267
#define NODE_TYPE_END
Definition: formatting.c:204
uint8 type
Definition: formatting.c:198
const KeyWord * key
Definition: formatting.c:201
int tm_wday
Definition: pgtime.h:33
#define b_c_STR
Definition: formatting.c:245
#define S_THth(_s)
Definition: formatting.c:565
int tm_hour
Definition: pgtime.h:29
#define BC_STR
Definition: formatting.c:246
#define A_M_STR
Definition: formatting.c:266
static char * str_initcap_z(const char *buff, Oid collid)
Definition: formatting.c:2131
fsec_t fsec
Definition: formatting.c:511
static char * asc_tolower_z(const char *buff)
Definition: formatting.c:2137
#define AD_STR
Definition: formatting.c:241
int errcode(int sqlerrcode)
Definition: elog.c:570
struct pg_tm tm
Definition: formatting.c:510
#define p_m_STR
Definition: formatting.c:272
#define am_STR
Definition: formatting.c:269
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:2119
long int tm_gmtoff
Definition: pgtime.h:36
Definition: pgtime.h:25
char * localized_abbrev_months[12]
Definition: pg_locale.c:102
static char * str_numth(char *dest, char *num, int type)
Definition: formatting.c:1564
static const char *const rm_months_upper[]
Definition: formatting.c:295
int id
Definition: formatting.c:191
#define pm_STR
Definition: formatting.c:274
static struct pg_tm tm
Definition: localtime.c:108
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define sprintf
Definition: port.h:194
void pfree(void *pointer)
Definition: mcxt.c:1056
const char *const months[]
Definition: datetime.c:66
#define NODE_TYPE_ACTION
Definition: formatting.c:205
#define ERROR
Definition: elog.h:43
char character[MAX_MULTIBYTE_CHAR_LEN+1]
Definition: formatting.c:199
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4324
#define S_FM(_s)
Definition: formatting.c:571
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4378
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:69
#define A_D_STR
Definition: formatting.c:239
#define a_d_STR
Definition: formatting.c:240
#define ereport(elevel, rest)
Definition: elog.h:141
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define bc_STR
Definition: formatting.c:247
#define DCH_to_char_fsec(frac_fmt, frac_val)
#define S_TH_TYPE(_s)
Definition: formatting.c:568
static const char *const months_full[]
Definition: formatting.c:221
int len
Definition: formatting.c:190
char * localized_full_days[7]
Definition: pg_locale.c:101
int date2j(int y, int m, int d)
Definition: datetime.c:270
#define ad_STR
Definition: formatting.c:242
void cache_locale_time(void)
Definition: pg_locale.c:774
#define P_M_STR
Definition: formatting.c:271
static char * asc_toupper_z(const char *buff)
Definition: formatting.c:2143
#define ADJUST_YEAR(year, is_interval)
Definition: formatting.c:237
uint8 suffix
Definition: formatting.c:200
#define tmtcTzn(_X)
Definition: formatting.c:516
int tm_year
Definition: pgtime.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:784
static char * str_toupper_z(const char *buff, Oid collid)
Definition: formatting.c:2125
#define INVALID_FOR_INTERVAL
Definition: formatting.c:538
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:4435
int i
#define S_TM(_s)
Definition: formatting.c:573
int tm_yday
Definition: pgtime.h:34
#define PM_STR
Definition: formatting.c:273
#define AM_STR
Definition: formatting.c:268
#define TM_SUFFIX_LEN
Definition: formatting.c:579
int tm_sec
Definition: pgtime.h:27
char * localized_full_months[12]
Definition: pg_locale.c:103
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:157
char * localized_abbrev_days[7]
Definition: pg_locale.c:100
int tm_min
Definition: pgtime.h:28
static const char *const rm_months_lower[]
Definition: formatting.c:298
static const char *const days_short[]
Definition: formatting.c:226
#define B_C_STR
Definition: formatting.c:244

◆ do_to_timestamp()

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

Definition at line 4310 of file formatting.c.

References 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().

4313 {
4314  FormatNode *format = NULL;
4315  TmFromChar tmfc;
4316  int fmt_len;
4317  char *date_str;
4318  int fmask;
4319  bool incache = false;
4320 
4321  date_str = text_to_cstring(date_txt);
4322 
4323  ZERO_tmfc(&tmfc);
4324  ZERO_tm(tm);
4325  *fsec = 0;
4326  fmask = 0; /* bit mask for ValidateDate() */
4327 
4328  fmt_len = VARSIZE_ANY_EXHDR(fmt);
4329 
4330  if (fmt_len)
4331  {
4332  char *fmt_str;
4333 
4334  fmt_str = text_to_cstring(fmt);
4335 
4336  if (fmt_len > DCH_CACHE_SIZE)
4337  {
4338  /*
4339  * Allocate new memory if format picture is bigger than static
4340  * cache and do not use cache (call parser always)
4341  */
4342  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4343 
4344  parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index,
4345  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
4346  }
4347  else
4348  {
4349  /*
4350  * Use cache buffers
4351  */
4352  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, std);
4353 
4354  incache = true;
4355  format = ent->format;
4356  }
4357 
4358 #ifdef DEBUG_TO_FROM_CHAR
4359  /* dump_node(format, fmt_len); */
4360  /* dump_index(DCH_keywords, DCH_index); */
4361 #endif
4362 
4363  DCH_from_char(format, date_str, &tmfc, std, have_error);
4364  CHECK_ERROR;
4365 
4366  pfree(fmt_str);
4367 
4368  if (flags)
4369  *flags = DCH_datetime_type(format, have_error);
4370 
4371  if (!incache)
4372  {
4373  pfree(format);
4374  format = NULL;
4375  }
4376 
4377  CHECK_ERROR;
4378  }
4379 
4380  DEBUG_TMFC(&tmfc);
4381 
4382  /*
4383  * Convert to_date/to_timestamp input fields to standard 'tm'
4384  */
4385  if (tmfc.ssss)
4386  {
4387  int x = tmfc.ssss;
4388 
4389  tm->tm_hour = x / SECS_PER_HOUR;
4390  x %= SECS_PER_HOUR;
4391  tm->tm_min = x / SECS_PER_MINUTE;
4392  x %= SECS_PER_MINUTE;
4393  tm->tm_sec = x;
4394  }
4395 
4396  if (tmfc.ss)
4397  tm->tm_sec = tmfc.ss;
4398  if (tmfc.mi)
4399  tm->tm_min = tmfc.mi;
4400  if (tmfc.hh)
4401  tm->tm_hour = tmfc.hh;
4402 
4403  if (tmfc.clock == CLOCK_12_HOUR)
4404  {
4405  if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
4406  {
4408  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4409  errmsg("hour \"%d\" is invalid for the 12-hour clock",
4410  tm->tm_hour),
4411  errhint("Use the 24-hour clock, or give an hour between 1 and 12."))));
4412  }
4413 
4414  if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
4415  tm->tm_hour += HOURS_PER_DAY / 2;
4416  else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
4417  tm->tm_hour = 0;
4418  }
4419 
4420  if (tmfc.year)
4421  {
4422  /*
4423  * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
4424  * the year in the given century. Keep in mind that the 21st century
4425  * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
4426  * 600BC to 501BC.
4427  */
4428  if (tmfc.cc && tmfc.yysz <= 2)
4429  {
4430  if (tmfc.bc)
4431  tmfc.cc = -tmfc.cc;
4432  tm->tm_year = tmfc.year % 100;
4433  if (tm->tm_year)
4434  {
4435  if (tmfc.cc >= 0)
4436  tm->tm_year += (tmfc.cc - 1) * 100;
4437  else
4438  tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
4439  }
4440  else
4441  {
4442  /* find century year for dates ending in "00" */
4443  tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
4444  }
4445  }
4446  else
4447  {
4448  /* If a 4-digit year is provided, we use that and ignore CC. */
4449  tm->tm_year = tmfc.year;
4450  if (tmfc.bc && tm->tm_year > 0)
4451  tm->tm_year = -(tm->tm_year - 1);
4452  }
4453  fmask |= DTK_M(YEAR);
4454  }
4455  else if (tmfc.cc)
4456  {
4457  /* use first year of century */
4458  if (tmfc.bc)
4459  tmfc.cc = -tmfc.cc;
4460  if (tmfc.cc >= 0)
4461  /* +1 because 21st century started in 2001 */
4462  tm->tm_year = (tmfc.cc - 1) * 100 + 1;
4463  else
4464  /* +1 because year == 599 is 600 BC */
4465  tm->tm_year = tmfc.cc * 100 + 1;
4466  fmask |= DTK_M(YEAR);
4467  }
4468 
4469  if (tmfc.j)
4470  {
4471  j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4472  fmask |= DTK_DATE_M;
4473  }
4474 
4475  if (tmfc.ww)
4476  {
4477  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
4478  {
4479  /*
4480  * If tmfc.d is not set, then the date is left at the beginning of
4481  * the ISO week (Monday).
4482  */
4483  if (tmfc.d)
4484  isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4485  else
4486  isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4487  fmask |= DTK_DATE_M;
4488  }
4489  else
4490  tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
4491  }
4492 
4493  if (tmfc.w)
4494  tmfc.dd = (tmfc.w - 1) * 7 + 1;
4495  if (tmfc.dd)
4496  {
4497  tm->tm_mday = tmfc.dd;
4498  fmask |= DTK_M(DAY);
4499  }
4500  if (tmfc.mm)
4501  {
4502  tm->tm_mon = tmfc.mm;
4503  fmask |= DTK_M(MONTH);
4504  }
4505 
4506  if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
4507  {
4508  /*
4509  * The month and day field have not been set, so we use the
4510  * day-of-year field to populate them. Depending on the date mode,
4511  * this field may be interpreted as a Gregorian day-of-year, or an ISO
4512  * week date day-of-year.
4513  */
4514 
4515  if (!tm->tm_year && !tmfc.bc)
4516  {
4518  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4519  errmsg("cannot calculate day of year without year information"))));
4520  }
4521 
4522  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
4523  {
4524  int j0; /* zeroth day of the ISO year, in Julian */
4525 
4526  j0 = isoweek2j(tm->tm_year, 1) - 1;
4527 
4528  j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
4529  fmask |= DTK_DATE_M;
4530  }
4531  else
4532  {
4533  const int *y;
4534  int i;
4535 
4536  static const int ysum[2][13] = {
4537  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
4538  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
4539 
4540  y = ysum[isleap(tm->tm_year)];
4541 
4542  for (i = 1; i <= MONTHS_PER_YEAR; i++)
4543  {
4544  if (tmfc.ddd <= y[i])
4545  break;
4546  }
4547  if (tm->tm_mon <= 1)
4548  tm->tm_mon = i;
4549 
4550  if (tm->tm_mday <= 1)
4551  tm->tm_mday = tmfc.ddd - y[i - 1];
4552 
4553  fmask |= DTK_M(MONTH) | DTK_M(DAY);
4554  }
4555  }
4556 
4557  if (tmfc.ms)
4558  *fsec += tmfc.ms * 1000;
4559  if (tmfc.us)
4560  *fsec += tmfc.us;
4561  if (fprec)
4562  *fprec = tmfc.ff; /* fractional precision, if specified */
4563 
4564  /* Range-check date fields according to bit mask computed above */
4565  if (fmask != 0)
4566  {
4567  /* We already dealt with AD/BC, so pass isjulian = true */
4568  int dterr = ValidateDate(fmask, true, false, false, tm);
4569 
4570  if (dterr != 0)
4571  {
4572  /*
4573  * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
4574  * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
4575  * irrelevant hint about datestyle.
4576  */
4577  RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
4578  }
4579  }
4580 
4581  /* Range-check time fields too */
4582  if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
4583  tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
4584  tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
4585  *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
4586  {
4587  RETURN_ERROR(DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp"));
4588  }
4589 
4590  /* Save parsed time-zone into tm->tm_zone if it was specified */
4591  if (tmfc.tzsign)
4592  {
4593  char *tz;
4594 
4595  if (tmfc.tzh < 0 || tmfc.tzh > MAX_TZDISP_HOUR ||
4596  tmfc.tzm < 0 || tmfc.tzm >= MINS_PER_HOUR)
4597  {
4598  RETURN_ERROR(DateTimeParseError(DTERR_TZDISP_OVERFLOW, date_str, "timestamp"));
4599  }
4600 
4601  tz = psprintf("%c%02d:%02d",
4602  tmfc.tzsign > 0 ? '+' : '-', tmfc.tzh, tmfc.tzm);
4603 
4604  tm->tm_zone = tz;
4605  }
4606 
4607  DEBUG_TM(tm);
4608 
4609 on_error:
4610 
4611  if (format && !incache)
4612  pfree(format);
4613 
4614  pfree(date_str);
4615 }
#define DEBUG_TM(_X)
Definition: formatting.c:501
#define DAY
Definition: datetime.h:94
int errhint(const char *fmt,...)
Definition: elog.c:974
void DateTimeParseError(int dterr, const char *str, const char *datatype)
Definition: datetime.c:3739
static void DCH_from_char(FormatNode *node, char *in, TmFromChar *out, bool std, bool *have_error)
Definition: formatting.c:3169
#define USECS_PER_SEC
Definition: timestamp.h:94
static int DCH_datetime_type(FormatNode *node, bool *have_error)
Definition: formatting.c:3662
#define YEAR
Definition: datetime.h:93
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:581
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:955
int errcode(int sqlerrcode)
Definition: elog.c:570
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:4306
FromCharDateMode mode
Definition: formatting.c:455
#define CHECK_ERROR
Definition: formatting.c:132
#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:1056
#define DCH_CACHE_SIZE
Definition: formatting.c:413
#define ERROR
Definition: elog.h:43
#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:423
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:1332
const char * tm_zone
Definition: pgtime.h:37
#define ereport(elevel, rest)
Definition: elog.h:141
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:295
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define CLOCK_12_HOUR
Definition: formatting.c:214
#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:4293
#define ZERO_tmfc(_X)
Definition: formatting.c:481
int isoweek2j(int year, int week)
Definition: timestamp.c:4273
#define DCH_FLAG
Definition: formatting.c:142
#define DEBUG_TMFC(_X)
Definition: formatting.c:500
char * text_to_cstring(const text *t)
Definition: varlena.c:204
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
static const KeyWord DCH_keywords[]
Definition: formatting.c:785
int i
#define STD_FLAG
Definition: formatting.c:144
#define DTK_M(t)
Definition: datetime.h:188
static char format
Definition: pg_basebackup.c:85
int tm_sec
Definition: pgtime.h:27
#define ZERO_tm(_X)
Definition: formatting.c:519
int tm_min
Definition: pgtime.h:28
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:3847
#define RETURN_ERROR(throw_error)
Definition: formatting.c:119
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2451

◆ fill_str()

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

Definition at line 4624 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().

4625 {
4626  memset(str, c, max);
4627  *(str + max) = '\0';
4628  return str;
4629 }
char * c

◆ float4_to_char()

Datum float4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6315 of file formatting.c.

References fill_str(), format, int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, isinf(), 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(), rint(), sign, val, and value.

6316 {
6318  text *fmt = PG_GETARG_TEXT_PP(1);
6319  NUMDesc Num;
6320  FormatNode *format;
6321  text *result;
6322  bool shouldFree;
6323  int out_pre_spaces = 0,
6324  sign = 0;
6325  char *numstr,
6326  *orgnum,
6327  *p;
6328 
6330 
6331  if (IS_ROMAN(&Num))
6332  numstr = orgnum = int_to_roman((int) rint(value));
6333  else if (IS_EEEE(&Num))
6334  {
6335  if (isnan(value) || isinf(value))
6336  {
6337  /*
6338  * Allow 6 characters for the leading sign, the decimal point,
6339  * "e", the exponent's sign and two exponent digits.
6340  */
6341  numstr = (char *) palloc(Num.pre + Num.post + 7);
6342  fill_str(numstr, '#', Num.pre + Num.post + 6);
6343  *numstr = ' ';
6344  *(numstr + Num.pre + 1) = '.';
6345  }
6346  else
6347  {
6348  numstr = orgnum = psprintf("%+.*e", Num.post, value);
6349 
6350  /*
6351  * Swap a leading positive sign for a space.
6352  */
6353  if (*orgnum == '+')
6354  *orgnum = ' ';
6355 
6356  numstr = orgnum;
6357  }
6358  }
6359  else
6360  {
6361  float4 val = value;
6362  int numstr_pre_len;
6363 
6364  if (IS_MULTI(&Num))
6365  {
6366  float multi = pow((double) 10, (double) Num.multi);
6367 
6368  val = value * multi;
6369  Num.pre += Num.multi;
6370  }
6371 
6372  orgnum = (char *) psprintf("%.0f", fabs(val));
6373  numstr_pre_len = strlen(orgnum);
6374 
6375  /* adjust post digits to fit max float digits */
6376  if (numstr_pre_len >= FLT_DIG)
6377  Num.post = 0;
6378  else if (numstr_pre_len + Num.post > FLT_DIG)
6379  Num.post = FLT_DIG - numstr_pre_len;
6380  orgnum = psprintf("%.*f", Num.post, val);
6381 
6382  if (*orgnum == '-')
6383  { /* < 0 */
6384  sign = '-';
6385  numstr = orgnum + 1;
6386  }
6387  else
6388  {
6389  sign = '+';
6390  numstr = orgnum;
6391  }
6392 
6393  if ((p = strchr(numstr, '.')))
6394  numstr_pre_len = p - numstr;
6395  else
6396  numstr_pre_len = strlen(numstr);
6397 
6398  /* needs padding? */
6399  if (numstr_pre_len < Num.pre)
6400  out_pre_spaces = Num.pre - numstr_pre_len;
6401  /* overflowed prefix digit format? */
6402  else if (numstr_pre_len > Num.pre)
6403  {
6404  numstr = (char *) palloc(Num.pre + Num.post + 2);
6405  fill_str(numstr, '#', Num.pre + Num.post + 1);
6406  *(numstr + Num.pre) = '.';
6407  }
6408  }
6409 
6411  PG_RETURN_TEXT_P(result);
6412 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define IS_EEEE(_f)
Definition: formatting.c:388
static struct @145 value
#define NUM_TOCHAR_finish
Definition: formatting.c:5903
#define IS_ROMAN(_f)
Definition: formatting.c:386
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define NUM_TOCHAR_prepare
Definition: formatting.c:5890
#define IS_MULTI(_f)
Definition: formatting.c:387
int isinf(double x)
char sign
Definition: informix.c:688
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:4624
static char * int_to_roman(int number)
Definition: formatting.c:4824
int pre
Definition: formatting.c:339
double rint(double x)
Definition: rint.c:21
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:275
float float4
Definition: c.h:490
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
int post
Definition: formatting.c:339
void * palloc(Size size)
Definition: mcxt.c:949
int multi
Definition: formatting.c:339
Definition: c.h:549
static char format
Definition: pg_basebackup.c:85
long val
Definition: informix.c:684

◆ float8_to_char()

Datum float8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6419 of file formatting.c.

References fill_str(), format, int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, isinf(), 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(), rint(), sign, val, and value.

6420 {
6422  text *fmt = PG_GETARG_TEXT_PP(1);
6423  NUMDesc Num;
6424  FormatNode *format;
6425  text *result;
6426  bool shouldFree;
6427  int out_pre_spaces = 0,
6428  sign = 0;
6429  char *numstr,
6430  *orgnum,
6431  *p;
6432 
6434 
6435  if (IS_ROMAN(&Num))
6436  numstr = orgnum = int_to_roman((int) rint(value));
6437  else if (IS_EEEE(&Num))
6438  {
6439  if (isnan(value) || isinf(value))
6440  {
6441  /*
6442  * Allow 6 characters for the leading sign, the decimal point,
6443  * "e", the exponent's sign and two exponent digits.
6444  */
6445  numstr = (char *) palloc(Num.pre + Num.post + 7);
6446  fill_str(numstr, '#', Num.pre + Num.post + 6);
6447  *numstr = ' ';
6448  *(numstr + Num.pre + 1) = '.';
6449  }
6450  else
6451  {
6452  numstr = orgnum = (char *) psprintf("%+.*e", Num.post, value);
6453 
6454  /*
6455  * Swap a leading positive sign for a space.
6456  */
6457  if (*orgnum == '+')
6458  *orgnum = ' ';
6459 
6460  numstr = orgnum;
6461  }
6462  }
6463  else
6464  {
6465  float8 val = value;
6466  int numstr_pre_len;
6467 
6468  if (IS_MULTI(&Num))
6469  {
6470  double multi = pow((double) 10, (double) Num.multi);
6471 
6472  val = value * multi;
6473  Num.pre += Num.multi;
6474  }
6475  orgnum = psprintf("%.0f", fabs(val));
6476  numstr_pre_len = strlen(orgnum);
6477 
6478  /* adjust post digits to fit max double digits */
6479  if (numstr_pre_len >= DBL_DIG)
6480  Num.post = 0;
6481  else if (numstr_pre_len + Num.post > DBL_DIG)
6482  Num.post = DBL_DIG - numstr_pre_len;
6483  orgnum = psprintf("%.*f", Num.post, val);
6484 
6485  if (*orgnum == '-')
6486  { /* < 0 */
6487  sign = '-';
6488  numstr = orgnum + 1;
6489  }
6490  else
6491  {
6492  sign = '+';
6493  numstr = orgnum;
6494  }
6495 
6496  if ((p = strchr(numstr, '.')))
6497  numstr_pre_len = p - numstr;
6498  else
6499  numstr_pre_len = strlen(numstr);
6500 
6501  /* needs padding? */
6502  if (numstr_pre_len < Num.pre)
6503  out_pre_spaces = Num.pre - numstr_pre_len;
6504  /* overflowed prefix digit format? */
6505  else if (numstr_pre_len > Num.pre)
6506  {
6507  numstr = (char *) palloc(Num.pre + Num.post + 2);
6508  fill_str(numstr, '#', Num.pre + Num.post + 1);
6509  *(numstr + Num.pre) = '.';
6510  }
6511  }
6512 
6514  PG_RETURN_TEXT_P(result);
6515 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:276
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define IS_EEEE(_f)
Definition: formatting.c:388
static struct @145 value
#define NUM_TOCHAR_finish
Definition: formatting.c:5903
#define IS_ROMAN(_f)
Definition: formatting.c:386
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define NUM_TOCHAR_prepare
Definition: formatting.c:5890
double float8
Definition: c.h:491
#define IS_MULTI(_f)
Definition: formatting.c:387
int isinf(double x)
char sign
Definition: informix.c:688
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:4624
static char * int_to_roman(int number)
Definition: formatting.c:4824
int pre
Definition: formatting.c:339
double rint(double x)
Definition: rint.c:21
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
int post
Definition: formatting.c:339
void * palloc(Size size)
Definition: mcxt.c:949
int multi
Definition: formatting.c:339
Definition: c.h:549
static char format
Definition: pg_basebackup.c:85
long val
Definition: informix.c:684

◆ from_char_parse_int()

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

Definition at line 2451 of file formatting.c.

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

Referenced by DCH_from_char().

2452 {
2453  return from_char_parse_int_len(dest, src, node->key->len, node, have_error);
2454 }
const KeyWord * key
Definition: formatting.c:201
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node, bool *have_error)
Definition: formatting.c:2351
int len
Definition: formatting.c:190

◆ from_char_parse_int_len()

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

Definition at line 2351 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().

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

◆ from_char_seq_search()

static int from_char_seq_search ( int *  dest,
char **  src,
const char *const *  array,
int  type,
int  max,