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 <wctype.h>
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "nodes/miscnodes.h"
#include "parser/scansup.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/formatting.h"
#include "utils/memutils.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
#include "varatt.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  fmt_tm
 
struct  TmToChar
 
struct  NUMProc
 

Macros

#define DCH_FLAG   0x1 /* DATE-TIME flag */
 
#define NUM_FLAG   0x2 /* NUMBER flag */
 
#define STD_FLAG   0x4 /* STANDARD flag */
 
#define KeyWord_INDEX_SIZE   ('~' - ' ')
 
#define KeyWord_INDEX_FILTER(_c)   ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
 
#define DCH_MAX_ITEM_SIZ   12 /* max localized day name */
 
#define NUM_MAX_ITEM_SIZ   8 /* roman number (RN has 15 chars) */
 
#define NODE_TYPE_END   1
 
#define NODE_TYPE_ACTION   2
 
#define NODE_TYPE_CHAR   3
 
#define NODE_TYPE_SEPARATOR   4
 
#define NODE_TYPE_SPACE   5
 
#define SUFFTYPE_PREFIX   1
 
#define SUFFTYPE_POSTFIX   2
 
#define CLOCK_24_HOUR   0
 
#define CLOCK_12_HOUR   1
 
#define ADJUST_YEAR(year, is_interval)   ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
 
#define A_D_STR   "A.D."
 
#define a_d_STR   "a.d."
 
#define AD_STR   "AD"
 
#define ad_STR   "ad"
 
#define B_C_STR   "B.C."
 
#define b_c_STR   "b.c."
 
#define BC_STR   "BC"
 
#define bc_STR   "bc"
 
#define A_M_STR   "A.M."
 
#define a_m_STR   "a.m."
 
#define AM_STR   "AM"
 
#define am_STR   "am"
 
#define P_M_STR   "P.M."
 
#define p_m_STR   "p.m."
 
#define PM_STR   "PM"
 
#define pm_STR   "pm"
 
#define TH_UPPER   1
 
#define TH_LOWER   2
 
#define NUM_F_DECIMAL   (1 << 1)
 
#define NUM_F_LDECIMAL   (1 << 2)
 
#define NUM_F_ZERO   (1 << 3)
 
#define NUM_F_BLANK   (1 << 4)
 
#define NUM_F_FILLMODE   (1 << 5)
 
#define NUM_F_LSIGN   (1 << 6)
 
#define NUM_F_BRACKET   (1 << 7)
 
#define NUM_F_MINUS   (1 << 8)
 
#define NUM_F_PLUS   (1 << 9)
 
#define NUM_F_ROMAN   (1 << 10)
 
#define NUM_F_MULTI   (1 << 11)
 
#define NUM_F_PLUS_POST   (1 << 12)
 
#define NUM_F_MINUS_POST   (1 << 13)
 
#define NUM_F_EEEE   (1 << 14)
 
#define NUM_LSIGN_PRE   (-1)
 
#define NUM_LSIGN_POST   1
 
#define NUM_LSIGN_NONE   0
 
#define IS_DECIMAL(_f)   ((_f)->flag & NUM_F_DECIMAL)
 
#define IS_LDECIMAL(_f)   ((_f)->flag & NUM_F_LDECIMAL)
 
#define IS_ZERO(_f)   ((_f)->flag & NUM_F_ZERO)
 
#define IS_BLANK(_f)   ((_f)->flag & NUM_F_BLANK)
 
#define IS_FILLMODE(_f)   ((_f)->flag & NUM_F_FILLMODE)
 
#define IS_BRACKET(_f)   ((_f)->flag & NUM_F_BRACKET)
 
#define IS_MINUS(_f)   ((_f)->flag & NUM_F_MINUS)
 
#define IS_LSIGN(_f)   ((_f)->flag & NUM_F_LSIGN)
 
#define IS_PLUS(_f)   ((_f)->flag & NUM_F_PLUS)
 
#define IS_ROMAN(_f)   ((_f)->flag & NUM_F_ROMAN)
 
#define IS_MULTI(_f)   ((_f)->flag & NUM_F_MULTI)
 
#define IS_EEEE(_f)   ((_f)->flag & NUM_F_EEEE)
 
#define DCH_CACHE_OVERHEAD    MAXALIGN(sizeof(bool) + sizeof(int))
 
#define NUM_CACHE_OVERHEAD    MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
 
#define DCH_CACHE_SIZE    ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
 
#define NUM_CACHE_SIZE    ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
 
#define DCH_CACHE_ENTRIES   20
 
#define NUM_CACHE_ENTRIES   20
 
#define ZERO_tmfc(_X)   memset(_X, 0, sizeof(TmFromChar))
 
#define DEBUG_TMFC(_X)
 
#define DEBUG_TM(_X)
 
#define tmtcTm(_X)   (&(_X)->tm)
 
#define tmtcTzn(_X)   ((_X)->tzn)
 
#define tmtcFsec(_X)   ((_X)->fsec)
 
#define COPY_tm(_DST, _SRC)
 
#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_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_last_
}
 
enum  NUM_poz {
  NUM_COMMA , NUM_DEC , NUM_0 , NUM_9 ,
  NUM_B , NUM_C , NUM_D , NUM_E ,
  NUM_FM , NUM_G , NUM_L , NUM_MI ,
  NUM_PL , NUM_PR , NUM_RN , NUM_SG ,
  NUM_SP , NUM_S , NUM_TH , NUM_V ,
  NUM_b , NUM_c , NUM_d , NUM_e ,
  NUM_fm , NUM_g , NUM_l , NUM_mi ,
  NUM_pl , NUM_pr , NUM_rn , NUM_sg ,
  NUM_sp , NUM_s , NUM_th , NUM_v ,
  _NUM_last_
}
 

Functions

static const KeyWordindex_seq_search (const char *str, const KeyWord *kw, const int *index)
 
static const KeySuffixsuff_search (const char *str, const KeySuffix *suf, int type)
 
static bool is_separator_char (const char *str)
 
static void NUMDesc_prepare (NUMDesc *num, FormatNode *n)
 
static void parse_format (FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, uint32 flags, NUMDesc *Num)
 
static void DCH_to_char (FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
 
static void DCH_from_char (FormatNode *node, const char *in, TmFromChar *out, Oid collid, bool std, Node *escontext)
 
static const char * get_th (char *num, int type)
 
static char * str_numth (char *dest, char *num, int type)
 
static int adjust_partial_year_to_2020 (int year)
 
static int strspace_len (const char *str)
 
static bool from_char_set_mode (TmFromChar *tmfc, const FromCharDateMode mode, Node *escontext)
 
static bool from_char_set_int (int *dest, const int value, const FormatNode *node, Node *escontext)
 
static int from_char_parse_int_len (int *dest, const char **src, const int len, FormatNode *node, Node *escontext)
 
static int from_char_parse_int (int *dest, const char **src, FormatNode *node, Node *escontext)
 
static int seq_search_ascii (const char *name, const char *const *array, int *len)
 
static int seq_search_localized (const char *name, char **array, int *len, Oid collid)
 
static bool from_char_seq_search (int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, Node *escontext)
 
static bool do_to_timestamp (text *date_txt, text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, int *fprec, uint32 *flags, Node *escontext)
 
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)
 
static textdatetime_to_char_body (TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
 
Datum timestamp_to_char (PG_FUNCTION_ARGS)
 
Datum timestamptz_to_char (PG_FUNCTION_ARGS)
 
Datum interval_to_char (PG_FUNCTION_ARGS)
 
Datum to_timestamp (PG_FUNCTION_ARGS)
 
Datum to_date (PG_FUNCTION_ARGS)
 
Datum parse_datetime (text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, Node *escontext)
 
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 195 of file formatting.c.

◆ a_d_STR

#define a_d_STR   "a.d."

Definition at line 196 of file formatting.c.

◆ A_M_STR

#define A_M_STR   "A.M."

Definition at line 222 of file formatting.c.

◆ a_m_STR

#define a_m_STR   "a.m."

Definition at line 223 of file formatting.c.

◆ AD_STR

#define AD_STR   "AD"

Definition at line 197 of file formatting.c.

◆ ad_STR

#define ad_STR   "ad"

Definition at line 198 of file formatting.c.

◆ ADJUST_YEAR

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

Definition at line 193 of file formatting.c.

◆ AM_STR

#define AM_STR   "AM"

Definition at line 224 of file formatting.c.

◆ am_STR

#define am_STR   "am"

Definition at line 225 of file formatting.c.

◆ AMOUNT_TEST

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

Definition at line 5149 of file formatting.c.

◆ B_C_STR

#define B_C_STR   "B.C."

Definition at line 200 of file formatting.c.

◆ b_c_STR

#define b_c_STR   "b.c."

Definition at line 201 of file formatting.c.

◆ BC_STR

#define BC_STR   "BC"

Definition at line 202 of file formatting.c.

◆ bc_STR

#define bc_STR   "bc"

Definition at line 203 of file formatting.c.

◆ CLOCK_12_HOUR

#define CLOCK_12_HOUR   1

Definition at line 170 of file formatting.c.

◆ CLOCK_24_HOUR

#define CLOCK_24_HOUR   0

Definition at line 169 of file formatting.c.

◆ COPY_tm

#define COPY_tm (   _DST,
  _SRC 
)
Value:
do { \
(_DST)->tm_sec = (_SRC)->tm_sec; \
(_DST)->tm_min = (_SRC)->tm_min; \
(_DST)->tm_hour = (_SRC)->tm_hour; \
(_DST)->tm_mday = (_SRC)->tm_mday; \
(_DST)->tm_mon = (_SRC)->tm_mon; \
(_DST)->tm_year = (_SRC)->tm_year; \
(_DST)->tm_wday = (_SRC)->tm_wday; \
(_DST)->tm_yday = (_SRC)->tm_yday; \
(_DST)->tm_gmtoff = (_SRC)->tm_gmtoff; \
} while(0)

Definition at line 483 of file formatting.c.

◆ DCH_CACHE_ENTRIES

#define DCH_CACHE_ENTRIES   20

Definition at line 364 of file formatting.c.

◆ DCH_CACHE_OVERHEAD

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

Definition at line 354 of file formatting.c.

◆ DCH_CACHE_SIZE

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

Definition at line 359 of file formatting.c.

◆ DCH_DATED

#define DCH_DATED   0x01

Definition at line 1015 of file formatting.c.

◆ DCH_FLAG

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

Definition at line 98 of file formatting.c.

◆ DCH_MAX_ITEM_SIZ

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

Definition at line 113 of file formatting.c.

◆ DCH_S_FM

#define DCH_S_FM   0x01

Definition at line 531 of file formatting.c.

◆ DCH_S_SP

#define DCH_S_SP   0x08

Definition at line 534 of file formatting.c.

◆ DCH_S_TH

#define DCH_S_TH   0x02

Definition at line 532 of file formatting.c.

◆ DCH_S_th

#define DCH_S_th   0x04

Definition at line 533 of file formatting.c.

◆ DCH_S_TM

#define DCH_S_TM   0x10

Definition at line 535 of file formatting.c.

◆ DCH_TIMED

#define DCH_TIMED   0x02

Definition at line 1016 of file formatting.c.

◆ 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_TH_TYPE(_s)
Definition: formatting.c:544
#define S_THth(_s)
Definition: formatting.c:541
#define sprintf
Definition: port.h:240

◆ DCH_ZONED

#define DCH_ZONED   0x04

Definition at line 1017 of file formatting.c.

◆ DEBUG_TM

#define DEBUG_TM (   _X)

Definition at line 447 of file formatting.c.

◆ DEBUG_TMFC

#define DEBUG_TMFC (   _X)

Definition at line 446 of file formatting.c.

◆ 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:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39

Definition at line 514 of file formatting.c.

◆ IS_BLANK

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

Definition at line 326 of file formatting.c.

◆ IS_BRACKET

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

Definition at line 328 of file formatting.c.

◆ IS_DECIMAL

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

Definition at line 323 of file formatting.c.

◆ IS_EEEE

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

Definition at line 334 of file formatting.c.

◆ IS_FILLMODE

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

Definition at line 327 of file formatting.c.

◆ IS_LDECIMAL

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

Definition at line 324 of file formatting.c.

◆ IS_LSIGN

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

Definition at line 330 of file formatting.c.

◆ IS_MINUS

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

Definition at line 329 of file formatting.c.

◆ IS_MULTI

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

Definition at line 333 of file formatting.c.

◆ IS_PLUS

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

Definition at line 331 of file formatting.c.

◆ 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:325

Definition at line 5360 of file formatting.c.

◆ IS_ROMAN

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

Definition at line 332 of file formatting.c.

◆ IS_ZERO

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

Definition at line 325 of file formatting.c.

◆ KeyWord_INDEX_FILTER

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

Definition at line 107 of file formatting.c.

◆ KeyWord_INDEX_SIZE

#define KeyWord_INDEX_SIZE   ('~' - ' ')

Definition at line 106 of file formatting.c.

◆ NODE_TYPE_ACTION

#define NODE_TYPE_ACTION   2

Definition at line 161 of file formatting.c.

◆ NODE_TYPE_CHAR

#define NODE_TYPE_CHAR   3

Definition at line 162 of file formatting.c.

◆ NODE_TYPE_END

#define NODE_TYPE_END   1

Definition at line 160 of file formatting.c.

◆ NODE_TYPE_SEPARATOR

#define NODE_TYPE_SEPARATOR   4

Definition at line 163 of file formatting.c.

◆ NODE_TYPE_SPACE

#define NODE_TYPE_SPACE   5

Definition at line 164 of file formatting.c.

◆ NUM_CACHE_ENTRIES

#define NUM_CACHE_ENTRIES   20

Definition at line 365 of file formatting.c.

◆ NUM_CACHE_OVERHEAD

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

Definition at line 356 of file formatting.c.

◆ NUM_CACHE_SIZE

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

Definition at line 361 of file formatting.c.

◆ NUM_F_BLANK

#define NUM_F_BLANK   (1 << 4)

Definition at line 303 of file formatting.c.

◆ NUM_F_BRACKET

#define NUM_F_BRACKET   (1 << 7)

Definition at line 306 of file formatting.c.

◆ NUM_F_DECIMAL

#define NUM_F_DECIMAL   (1 << 1)

Definition at line 300 of file formatting.c.

◆ NUM_F_EEEE

#define NUM_F_EEEE   (1 << 14)

Definition at line 313 of file formatting.c.

◆ NUM_F_FILLMODE

#define NUM_F_FILLMODE   (1 << 5)

Definition at line 304 of file formatting.c.

◆ NUM_F_LDECIMAL

#define NUM_F_LDECIMAL   (1 << 2)

Definition at line 301 of file formatting.c.

◆ NUM_F_LSIGN

#define NUM_F_LSIGN   (1 << 6)

Definition at line 305 of file formatting.c.

◆ NUM_F_MINUS

#define NUM_F_MINUS   (1 << 8)

Definition at line 307 of file formatting.c.

◆ NUM_F_MINUS_POST

#define NUM_F_MINUS_POST   (1 << 13)

Definition at line 312 of file formatting.c.

◆ NUM_F_MULTI

#define NUM_F_MULTI   (1 << 11)

Definition at line 310 of file formatting.c.

◆ NUM_F_PLUS

#define NUM_F_PLUS   (1 << 9)

Definition at line 308 of file formatting.c.

◆ NUM_F_PLUS_POST

#define NUM_F_PLUS_POST   (1 << 12)

Definition at line 311 of file formatting.c.

◆ NUM_F_ROMAN

#define NUM_F_ROMAN   (1 << 10)

Definition at line 309 of file formatting.c.

◆ NUM_F_ZERO

#define NUM_F_ZERO   (1 << 3)

Definition at line 302 of file formatting.c.

◆ NUM_FLAG

#define NUM_FLAG   0x2 /* NUMBER flag */

Definition at line 99 of file formatting.c.

◆ NUM_LSIGN_NONE

#define NUM_LSIGN_NONE   0

Definition at line 317 of file formatting.c.

◆ NUM_LSIGN_POST

#define NUM_LSIGN_POST   1

Definition at line 316 of file formatting.c.

◆ NUM_LSIGN_PRE

#define NUM_LSIGN_PRE   (-1)

Definition at line 315 of file formatting.c.

◆ NUM_MAX_ITEM_SIZ

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

Definition at line 114 of file formatting.c.

◆ 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 VARHDRSZ
Definition: c.h:681
#define PG_GET_COLLATION()
Definition: fmgr.h:198
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:5574
char sign
Definition: informix.c:668
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
static char format
const void size_t len
#define VARDATA(PTR)
Definition: varatt.h:278

Definition at line 6071 of file formatting.c.

◆ NUM_TOCHAR_prepare

#define NUM_TOCHAR_prepare
Value:
do { \
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 NUM_MAX_ITEM_SIZ
Definition: formatting.c:114
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
Definition: formatting.c:4931
static void const char * fmt
void * palloc0(Size size)
Definition: mcxt.c:1257
Definition: c.h:676
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:184

Definition at line 6058 of file formatting.c.

◆ OVERLOAD_TEST

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

Definition at line 5148 of file formatting.c.

◆ P_M_STR

#define P_M_STR   "P.M."

Definition at line 227 of file formatting.c.

◆ p_m_STR

#define p_m_STR   "p.m."

Definition at line 228 of file formatting.c.

◆ PM_STR

#define PM_STR   "PM"

Definition at line 229 of file formatting.c.

◆ pm_STR

#define pm_STR   "pm"

Definition at line 230 of file formatting.c.

◆ S_FM

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

Definition at line 547 of file formatting.c.

◆ S_SP

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

Definition at line 548 of file formatting.c.

◆ S_TH

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

Definition at line 542 of file formatting.c.

◆ S_th

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

Definition at line 543 of file formatting.c.

◆ S_TH_TYPE

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

Definition at line 544 of file formatting.c.

◆ S_THth

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

Definition at line 541 of file formatting.c.

◆ S_TM

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

Definition at line 549 of file formatting.c.

◆ 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)
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1024

Definition at line 2119 of file formatting.c.

◆ STD_FLAG

#define STD_FLAG   0x4 /* STANDARD flag */

Definition at line 100 of file formatting.c.

◆ SUFFTYPE_POSTFIX

#define SUFFTYPE_POSTFIX   2

Definition at line 167 of file formatting.c.

◆ SUFFTYPE_PREFIX

#define SUFFTYPE_PREFIX   1

Definition at line 166 of file formatting.c.

◆ TH_LOWER

#define TH_LOWER   2

Definition at line 277 of file formatting.c.

◆ TH_UPPER

#define TH_UPPER   1

Definition at line 276 of file formatting.c.

◆ TM_SUFFIX_LEN

#define TM_SUFFIX_LEN   2

Definition at line 555 of file formatting.c.

◆ tmtcFsec

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

Definition at line 480 of file formatting.c.

◆ tmtcTm

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

Definition at line 478 of file formatting.c.

◆ tmtcTzn

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

Definition at line 479 of file formatting.c.

◆ ZERO_tm

#define ZERO_tm (   _X)
Value:
do { \
memset(_X, 0, sizeof(*(_X))); \
(_X)->tm_mday = (_X)->tm_mon = 1; \
} while(0)

Definition at line 497 of file formatting.c.

◆ ZERO_tmfc

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

Definition at line 427 of file formatting.c.

◆ 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:478

Definition at line 503 of file formatting.c.

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

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_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_last_ 

Definition at line 598 of file formatting.c.

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

◆ FromCharDateMode

Enumerator
FROM_CHAR_DATE_NONE 
FROM_CHAR_DATE_GREGORIAN 
FROM_CHAR_DATE_ISOWEEK 

Definition at line 136 of file formatting.c.

137 {
138  FROM_CHAR_DATE_NONE = 0, /* Value does not affect date mode. */
139  FROM_CHAR_DATE_GREGORIAN, /* Gregorian (day, month, year) style date */
140  FROM_CHAR_DATE_ISOWEEK, /* ISO 8601 week date */
FromCharDateMode
Definition: formatting.c:137
@ FROM_CHAR_DATE_ISOWEEK
Definition: formatting.c:140
@ FROM_CHAR_DATE_GREGORIAN
Definition: formatting.c:139
@ FROM_CHAR_DATE_NONE
Definition: formatting.c:138

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

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

Function Documentation

◆ adjust_partial_year_to_2020()

static int adjust_partial_year_to_2020 ( int  year)
static

Definition at line 2200 of file formatting.c.

2201 {
2202  /*
2203  * Adjust all dates toward 2020; this is effectively what happens when we
2204  * assume '70' is 1970 and '69' is 2069.
2205  */
2206  /* Force 0-69 into the 2000's */
2207  if (year < 70)
2208  return year + 2000;
2209  /* Force 70-99 into the 1900's */
2210  else if (year < 100)
2211  return year + 1900;
2212  /* Force 100-519 into the 2000's */
2213  else if (year < 520)
2214  return year + 2000;
2215  /* Force 520-999 into the 1000's */
2216  else if (year < 1000)
2217  return year + 1000;
2218  else
2219  return year;
2220 }

Referenced by DCH_from_char().

◆ asc_initcap()

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

Definition at line 2050 of file formatting.c.

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

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

Referenced by str_initcap().

◆ asc_tolower()

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

Definition at line 2004 of file formatting.c.

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

References pg_ascii_tolower(), and pnstrdup().

Referenced by asc_tolower_z(), and str_tolower().

◆ asc_tolower_z()

static char* asc_tolower_z ( const char *  buff)
static

Definition at line 2099 of file formatting.c.

2100 {
2101  return asc_tolower(buff, strlen(buff));
2102 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2004

References asc_tolower().

Referenced by DCH_to_char(), and NUM_processor().

◆ asc_toupper()

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

Definition at line 2027 of file formatting.c.

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

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

◆ asc_toupper_z()

static char* asc_toupper_z ( const char *  buff)
static

Definition at line 2105 of file formatting.c.

2106 {
2107  return asc_toupper(buff, strlen(buff));
2108 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2027

References asc_toupper().

Referenced by DCH_to_char().

◆ datetime_to_char_body()

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

Definition at line 3975 of file formatting.c.

3976 {
3977  FormatNode *format;
3978  char *fmt_str,
3979  *result;
3980  bool incache;
3981  int fmt_len;
3982  text *res;
3983 
3984  /*
3985  * Convert fmt to C string
3986  */
3987  fmt_str = text_to_cstring(fmt);
3988  fmt_len = strlen(fmt_str);
3989 
3990  /*
3991  * Allocate workspace for result as C string
3992  */
3993  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
3994  *result = '\0';
3995 
3996  if (fmt_len > DCH_CACHE_SIZE)
3997  {
3998  /*
3999  * Allocate new memory if format picture is bigger than static cache
4000  * and do not use cache (call parser always)
4001  */
4002  incache = false;
4003 
4004  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4005 
4006  parse_format(format, fmt_str, DCH_keywords,
4007  DCH_suff, DCH_index, DCH_FLAG, NULL);
4008  }
4009  else
4010  {
4011  /*
4012  * Use cache buffers
4013  */
4014  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
4015 
4016  incache = true;
4017  format = ent->format;
4018  }
4019 
4020  /* The real work is here */
4021  DCH_to_char(format, is_interval, tmtc, result, collid);
4022 
4023  if (!incache)
4024  pfree(format);
4025 
4026  pfree(fmt_str);
4027 
4028  /* convert C-string result to TEXT format */
4029  res = cstring_to_text(result);
4030 
4031  pfree(result);
4032  return res;
4033 }
Oid collid
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:937
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:1317
#define DCH_FLAG
Definition: formatting.c:98
static const KeySuffix DCH_suff[]
Definition: formatting.c:557
#define DCH_CACHE_SIZE
Definition: formatting.c:359
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
Definition: formatting.c:2611
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:113
static const KeyWord DCH_keywords[]
Definition: formatting.c:764
static DCHCacheEntry * DCH_cache_fetch(const char *str, bool std)
Definition: formatting.c:3948
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:369
char * text_to_cstring(const text *t)
Definition: varlena.c:217

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

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

◆ DCH_cache_fetch()

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

Definition at line 3948 of file formatting.c.

3949 {
3950  DCHCacheEntry *ent;
3951 
3952  if ((ent = DCH_cache_search(str, std)) == NULL)
3953  {
3954  /*
3955  * Not in the cache, must run parser and save a new format-picture to
3956  * the cache. Do not mark the cache entry valid until parsing
3957  * succeeds.
3958  */
3959  ent = DCH_cache_getnew(str, std);
3960 
3962  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
3963 
3964  ent->valid = true;
3965  }
3966  return ent;
3967 }
#define STD_FLAG
Definition: formatting.c:100
static DCHCacheEntry * DCH_cache_getnew(const char *str, bool std)
Definition: formatting.c:3867
static DCHCacheEntry * DCH_cache_search(const char *str, bool std)
Definition: formatting.c:3927

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

Referenced by datetime_to_char_body(), and do_to_timestamp().

◆ DCH_cache_getnew()

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

Definition at line 3867 of file formatting.c.

3868 {
3869  DCHCacheEntry *ent;
3870 
3871  /* Ensure we can advance DCHCounter below */
3873 
3874  /*
3875  * If cache is full, remove oldest entry (or recycle first not-valid one)
3876  */
3878  {
3879  DCHCacheEntry *old = DCHCache[0];
3880 
3881 #ifdef DEBUG_TO_FROM_CHAR
3882  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3883 #endif
3884  if (old->valid)
3885  {
3886  for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
3887  {
3888  ent = DCHCache[i];
3889  if (!ent->valid)
3890  {
3891  old = ent;
3892  break;
3893  }
3894  if (ent->age < old->age)
3895  old = ent;
3896  }
3897  }
3898 #ifdef DEBUG_TO_FROM_CHAR
3899  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3900 #endif
3901  old->valid = false;
3902  strlcpy(old->str, str, DCH_CACHE_SIZE + 1);
3903  old->age = (++DCHCounter);
3904  /* caller is expected to fill format, then set valid */
3905  return old;
3906  }
3907  else
3908  {
3909 #ifdef DEBUG_TO_FROM_CHAR
3910  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3911 #endif
3912  Assert(DCHCache[n_DCHCache] == NULL);
3913  DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
3915  ent->valid = false;
3916  strlcpy(ent->str, str, DCH_CACHE_SIZE + 1);
3917  ent->std = std;
3918  ent->age = (++DCHCounter);
3919  /* caller is expected to fill format, then set valid */
3920  ++n_DCHCache;
3921  return ent;
3922  }
3923 }
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3756
static int DCHCounter
Definition: formatting.c:388
static int n_DCHCache
Definition: formatting.c:387
static DCHCacheEntry * DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:386
#define DCH_CACHE_ENTRIES
Definition: formatting.c:364
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
MemoryContext TopMemoryContext
Definition: mcxt.c:141
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:370

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

Referenced by DCH_cache_fetch().

◆ DCH_cache_search()

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

Definition at line 3927 of file formatting.c.

3928 {
3929  /* Ensure we can advance DCHCounter below */
3931 
3932  for (int i = 0; i < n_DCHCache; i++)
3933  {
3934  DCHCacheEntry *ent = DCHCache[i];
3935 
3936  if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
3937  {
3938  ent->age = (++DCHCounter);
3939  return ent;
3940  }
3941  }
3942 
3943  return NULL;
3944 }

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

Referenced by DCH_cache_fetch().

◆ DCH_datetime_type()

static int DCH_datetime_type ( FormatNode node)
static

Definition at line 3770 of file formatting.c.

3771 {
3772  FormatNode *n;
3773  int flags = 0;
3774 
3775  for (n = node; n->type != NODE_TYPE_END; n++)
3776  {
3777  if (n->type != NODE_TYPE_ACTION)
3778  continue;
3779 
3780  switch (n->key->id)
3781  {
3782  case DCH_FX:
3783  break;
3784  case DCH_A_M:
3785  case DCH_P_M:
3786  case DCH_a_m:
3787  case DCH_p_m:
3788  case DCH_AM:
3789  case DCH_PM:
3790  case DCH_am:
3791  case DCH_pm:
3792  case DCH_HH:
3793  case DCH_HH12:
3794  case DCH_HH24:
3795  case DCH_MI:
3796  case DCH_SS:
3797  case DCH_MS: /* millisecond */
3798  case DCH_US: /* microsecond */
3799  case DCH_FF1:
3800  case DCH_FF2:
3801  case DCH_FF3:
3802  case DCH_FF4:
3803  case DCH_FF5:
3804  case DCH_FF6:
3805  case DCH_SSSS:
3806  flags |= DCH_TIMED;
3807  break;
3808  case DCH_tz:
3809  case DCH_TZ:
3810  case DCH_OF:
3811  case DCH_TZH:
3812  case DCH_TZM:
3813  flags |= DCH_ZONED;
3814  break;
3815  case DCH_A_D:
3816  case DCH_B_C:
3817  case DCH_a_d:
3818  case DCH_b_c:
3819  case DCH_AD:
3820  case DCH_BC:
3821  case DCH_ad:
3822  case DCH_bc:
3823  case DCH_MONTH:
3824  case DCH_Month:
3825  case DCH_month:
3826  case DCH_MON:
3827  case DCH_Mon:
3828  case DCH_mon:
3829  case DCH_MM:
3830  case DCH_DAY:
3831  case DCH_Day:
3832  case DCH_day:
3833  case DCH_DY:
3834  case DCH_Dy:
3835  case DCH_dy:
3836  case DCH_DDD:
3837  case DCH_IDDD:
3838  case DCH_DD:
3839  case DCH_D:
3840  case DCH_ID:
3841  case DCH_WW:
3842  case DCH_Q:
3843  case DCH_CC:
3844  case DCH_Y_YYY:
3845  case DCH_YYYY:
3846  case DCH_IYYY:
3847  case DCH_YYY:
3848  case DCH_IYY:
3849  case DCH_YY:
3850  case DCH_IY:
3851  case DCH_Y:
3852  case DCH_I:
3853  case DCH_RM:
3854  case DCH_rm:
3855  case DCH_W:
3856  case DCH_J:
3857  flags |= DCH_DATED;
3858  break;
3859  }
3860  }
3861 
3862  return flags;
3863 }
#define DCH_DATED
Definition: formatting.c:1015
#define DCH_TIMED
Definition: formatting.c:1016
#define NODE_TYPE_ACTION
Definition: formatting.c:161
#define DCH_ZONED
Definition: formatting.c:1017
#define NODE_TYPE_END
Definition: formatting.c:160
const KeyWord * key
Definition: formatting.c:157
uint8 type
Definition: formatting.c:154
int id
Definition: formatting.c:147

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, KeyWord::id, FormatNode::key, NODE_TYPE_ACTION, NODE_TYPE_END, and FormatNode::type.

Referenced by do_to_timestamp().

◆ DCH_from_char()

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

Definition at line 3258 of file formatting.c.

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

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

Referenced by do_to_timestamp().

◆ DCH_prevent_counter_overflow()

static void DCH_prevent_counter_overflow ( void  )
inlinestatic

Definition at line 3756 of file formatting.c.

3757 {
3758  if (DCHCounter >= (INT_MAX - 1))
3759  {
3760  for (int i = 0; i < n_DCHCache; i++)
3761  DCHCache[i]->age >>= 1;
3762  DCHCounter >>= 1;
3763  }
3764 }

References DCHCache, DCHCounter, i, and n_DCHCache.

Referenced by DCH_cache_getnew(), and DCH_cache_search().

◆ DCH_to_char()

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

Definition at line 2611 of file formatting.c.

2612 {
2613  FormatNode *n;
2614  char *s;
2615  struct fmt_tm *tm = &in->tm;
2616  int i;
2617 
2618  /* cache localized days and months */
2620 
2621  s = out;
2622  for (n = node; n->type != NODE_TYPE_END; n++)
2623  {
2624  if (n->type != NODE_TYPE_ACTION)
2625  {
2626  strcpy(s, n->character);
2627  s += strlen(s);
2628  continue;
2629  }
2630 
2631  switch (n->key->id)
2632  {
2633  case DCH_A_M:
2634  case DCH_P_M:
2635  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2636  ? P_M_STR : A_M_STR);
2637  s += strlen(s);
2638  break;
2639  case DCH_AM:
2640  case DCH_PM:
2641  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2642  ? PM_STR : AM_STR);
2643  s += strlen(s);
2644  break;
2645  case DCH_a_m:
2646  case DCH_p_m:
2647  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2648  ? p_m_STR : a_m_STR);
2649  s += strlen(s);
2650  break;
2651  case DCH_am:
2652  case DCH_pm:
2653  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2654  ? pm_STR : am_STR);
2655  s += strlen(s);
2656  break;
2657  case DCH_HH:
2658  case DCH_HH12:
2659 
2660  /*
2661  * display time as shown on a 12-hour clock, even for
2662  * intervals
2663  */
2664  sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2665  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ?
2666  (long long) (HOURS_PER_DAY / 2) :
2667  (long long) (tm->tm_hour % (HOURS_PER_DAY / 2)));
2668  if (S_THth(n->suffix))
2669  str_numth(s, s, S_TH_TYPE(n->suffix));
2670  s += strlen(s);
2671  break;
2672  case DCH_HH24:
2673  sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2674  (long long) tm->tm_hour);
2675  if (S_THth(n->suffix))
2676  str_numth(s, s, S_TH_TYPE(n->suffix));
2677  s += strlen(s);
2678  break;
2679  case DCH_MI:
2680  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2681  tm->tm_min);
2682  if (S_THth(n->suffix))
2683  str_numth(s, s, S_TH_TYPE(n->suffix));
2684  s += strlen(s);
2685  break;
2686  case DCH_SS:
2687  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2688  tm->tm_sec);
2689  if (S_THth(n->suffix))
2690  str_numth(s, s, S_TH_TYPE(n->suffix));
2691  s += strlen(s);
2692  break;
2693 
2694 #define DCH_to_char_fsec(frac_fmt, frac_val) \
2695  sprintf(s, frac_fmt, (int) (frac_val)); \
2696  if (S_THth(n->suffix)) \
2697  str_numth(s, s, S_TH_TYPE(n->suffix)); \
2698  s += strlen(s)
2699 
2700  case DCH_FF1: /* tenth of second */
2701  DCH_to_char_fsec("%01d", in->fsec / 100000);
2702  break;
2703  case DCH_FF2: /* hundredth of second */
2704  DCH_to_char_fsec("%02d", in->fsec / 10000);
2705  break;
2706  case DCH_FF3:
2707  case DCH_MS: /* millisecond */
2708  DCH_to_char_fsec("%03d", in->fsec / 1000);
2709  break;
2710  case DCH_FF4: /* tenth of a millisecond */
2711  DCH_to_char_fsec("%04d", in->fsec / 100);
2712  break;
2713  case DCH_FF5: /* hundredth of a millisecond */
2714  DCH_to_char_fsec("%05d", in->fsec / 10);
2715  break;
2716  case DCH_FF6:
2717  case DCH_US: /* microsecond */
2718  DCH_to_char_fsec("%06d", in->fsec);
2719  break;
2720 #undef DCH_to_char_fsec
2721  case DCH_SSSS:
2722  sprintf(s, "%lld",
2723  (long long) (tm->tm_hour * SECS_PER_HOUR +
2725  tm->tm_sec));
2726  if (S_THth(n->suffix))
2727  str_numth(s, s, S_TH_TYPE(n->suffix));
2728  s += strlen(s);
2729  break;
2730  case DCH_tz:
2732  if (tmtcTzn(in))
2733  {
2734  /* We assume here that timezone names aren't localized */
2735  char *p = asc_tolower_z(tmtcTzn(in));
2736 
2737  strcpy(s, p);
2738  pfree(p);
2739  s += strlen(s);
2740  }
2741  break;
2742  case DCH_TZ:
2744  if (tmtcTzn(in))
2745  {
2746  strcpy(s, tmtcTzn(in));
2747  s += strlen(s);
2748  }
2749  break;
2750  case DCH_TZH:
2752  sprintf(s, "%c%02d",
2753  (tm->tm_gmtoff >= 0) ? '+' : '-',
2754  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2755  s += strlen(s);
2756  break;
2757  case DCH_TZM:
2759  sprintf(s, "%02d",
2760  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2761  s += strlen(s);
2762  break;
2763  case DCH_OF:
2765  sprintf(s, "%c%0*d",
2766  (tm->tm_gmtoff >= 0) ? '+' : '-',
2767  S_FM(n->suffix) ? 0 : 2,
2768  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2769  s += strlen(s);
2770  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2771  {
2772  sprintf(s, ":%02d",
2773  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2774  s += strlen(s);
2775  }
2776  break;
2777  case DCH_A_D:
2778  case DCH_B_C:
2780  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2781  s += strlen(s);
2782  break;
2783  case DCH_AD:
2784  case DCH_BC:
2786  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2787  s += strlen(s);
2788  break;
2789  case DCH_a_d:
2790  case DCH_b_c:
2792  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2793  s += strlen(s);
2794  break;
2795  case DCH_ad:
2796  case DCH_bc:
2798  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2799  s += strlen(s);
2800  break;
2801  case DCH_MONTH:
2803  if (!tm->tm_mon)
2804  break;
2805  if (S_TM(n->suffix))
2806  {
2808 
2809  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2810  strcpy(s, str);
2811  else
2812  ereport(ERROR,
2813  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2814  errmsg("localized string format value too long")));
2815  }
2816  else
2817  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2819  s += strlen(s);
2820  break;
2821  case DCH_Month:
2823  if (!tm->tm_mon)
2824  break;
2825  if (S_TM(n->suffix))
2826  {
2828 
2829  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2830  strcpy(s, str);
2831  else
2832  ereport(ERROR,
2833  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2834  errmsg("localized string format value too long")));
2835  }
2836  else
2837  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2838  months_full[tm->tm_mon - 1]);
2839  s += strlen(s);
2840  break;
2841  case DCH_month:
2843  if (!tm->tm_mon)
2844  break;
2845  if (S_TM(n->suffix))
2846  {
2848 
2849  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2850  strcpy(s, str);
2851  else
2852  ereport(ERROR,
2853  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2854  errmsg("localized string format value too long")));
2855  }
2856  else
2857  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2859  s += strlen(s);
2860  break;
2861  case DCH_MON:
2863  if (!tm->tm_mon)
2864  break;
2865  if (S_TM(n->suffix))
2866  {
2868 
2869  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2870  strcpy(s, str);
2871  else
2872  ereport(ERROR,
2873  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2874  errmsg("localized string format value too long")));
2875  }
2876  else
2877  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2878  s += strlen(s);
2879  break;
2880  case DCH_Mon:
2882  if (!tm->tm_mon)
2883  break;
2884  if (S_TM(n->suffix))
2885  {
2887 
2888  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2889  strcpy(s, str);
2890  else
2891  ereport(ERROR,
2892  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2893  errmsg("localized string format value too long")));
2894  }
2895  else
2896  strcpy(s, months[tm->tm_mon - 1]);
2897  s += strlen(s);
2898  break;
2899  case DCH_mon:
2901  if (!tm->tm_mon)
2902  break;
2903  if (S_TM(n->suffix))
2904  {
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  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2916  s += strlen(s);
2917  break;
2918  case DCH_MM:
2919  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2920  tm->tm_mon);
2921  if (S_THth(n->suffix))
2922  str_numth(s, s, S_TH_TYPE(n->suffix));
2923  s += strlen(s);
2924  break;
2925  case DCH_DAY:
2927  if (S_TM(n->suffix))
2928  {
2930 
2931  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2932  strcpy(s, str);
2933  else
2934  ereport(ERROR,
2935  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2936  errmsg("localized string format value too long")));
2937  }
2938  else
2939  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2941  s += strlen(s);
2942  break;
2943  case DCH_Day:
2945  if (S_TM(n->suffix))
2946  {
2948 
2949  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2950  strcpy(s, str);
2951  else
2952  ereport(ERROR,
2953  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2954  errmsg("localized string format value too long")));
2955  }
2956  else
2957  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2958  days[tm->tm_wday]);
2959  s += strlen(s);
2960  break;
2961  case DCH_day:
2963  if (S_TM(n->suffix))
2964  {
2966 
2967  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2968  strcpy(s, str);
2969  else
2970  ereport(ERROR,
2971  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2972  errmsg("localized string format value too long")));
2973  }
2974  else
2975  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2977  s += strlen(s);
2978  break;
2979  case DCH_DY:
2981  if (S_TM(n->suffix))
2982  {
2984 
2985  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2986  strcpy(s, str);
2987  else
2988  ereport(ERROR,
2989  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2990  errmsg("localized string format value too long")));
2991  }
2992  else
2993  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
2994  s += strlen(s);
2995  break;
2996  case DCH_Dy:
2998  if (S_TM(n->suffix))
2999  {
3001 
3002  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3003  strcpy(s, str);
3004  else
3005  ereport(ERROR,
3006  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3007  errmsg("localized string format value too long")));
3008  }
3009  else
3010  strcpy(s, days_short[tm->tm_wday]);
3011  s += strlen(s);
3012  break;
3013  case DCH_dy:
3015  if (S_TM(n->suffix))
3016  {
3018 
3019  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3020  strcpy(s, str);
3021  else
3022  ereport(ERROR,
3023  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3024  errmsg("localized string format value too long")));
3025  }
3026  else
3027  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
3028  s += strlen(s);
3029  break;
3030  case DCH_DDD:
3031  case DCH_IDDD:
3032  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
3033  (n->key->id == DCH_DDD) ?
3034  tm->tm_yday :
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_DD:
3041  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
3042  if (S_THth(n->suffix))
3043  str_numth(s, s, S_TH_TYPE(n->suffix));
3044  s += strlen(s);
3045  break;
3046  case DCH_D:
3048  sprintf(s, "%d", tm->tm_wday + 1);
3049  if (S_THth(n->suffix))
3050  str_numth(s, s, S_TH_TYPE(n->suffix));
3051  s += strlen(s);
3052  break;
3053  case DCH_ID:
3055  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
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_WW:
3061  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3062  (tm->tm_yday - 1) / 7 + 1);
3063  if (S_THth(n->suffix))
3064  str_numth(s, s, S_TH_TYPE(n->suffix));
3065  s += strlen(s);
3066  break;
3067  case DCH_IW:
3068  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3070  if (S_THth(n->suffix))
3071  str_numth(s, s, S_TH_TYPE(n->suffix));
3072  s += strlen(s);
3073  break;
3074  case DCH_Q:
3075  if (!tm->tm_mon)
3076  break;
3077  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
3078  if (S_THth(n->suffix))
3079  str_numth(s, s, S_TH_TYPE(n->suffix));
3080  s += strlen(s);
3081  break;
3082  case DCH_CC:
3083  if (is_interval) /* straight calculation */
3084  i = tm->tm_year / 100;
3085  else
3086  {
3087  if (tm->tm_year > 0)
3088  /* Century 20 == 1901 - 2000 */
3089  i = (tm->tm_year - 1) / 100 + 1;
3090  else
3091  /* Century 6BC == 600BC - 501BC */
3092  i = tm->tm_year / 100 - 1;
3093  }
3094  if (i <= 99 && i >= -99)
3095  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
3096  else
3097  sprintf(s, "%d", i);
3098  if (S_THth(n->suffix))
3099  str_numth(s, s, S_TH_TYPE(n->suffix));
3100  s += strlen(s);
3101  break;
3102  case DCH_Y_YYY:
3103  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
3104  sprintf(s, "%d,%03d", i,
3105  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
3106  if (S_THth(n->suffix))
3107  str_numth(s, s, S_TH_TYPE(n->suffix));
3108  s += strlen(s);
3109  break;
3110  case DCH_YYYY:
3111  case DCH_IYYY:
3112  sprintf(s, "%0*d",
3113  S_FM(n->suffix) ? 0 :
3114  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
3115  (n->key->id == DCH_YYYY ?
3116  ADJUST_YEAR(tm->tm_year, is_interval) :
3118  tm->tm_mon,
3119  tm->tm_mday),
3120  is_interval)));
3121  if (S_THth(n->suffix))
3122  str_numth(s, s, S_TH_TYPE(n->suffix));
3123  s += strlen(s);
3124  break;
3125  case DCH_YYY:
3126  case DCH_IYY:
3127  sprintf(s, "%0*d",
3128  S_FM(n->suffix) ? 0 :
3129  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
3130  (n->key->id == DCH_YYY ?
3131  ADJUST_YEAR(tm->tm_year, is_interval) :
3133  tm->tm_mon,
3134  tm->tm_mday),
3135  is_interval)) % 1000);
3136  if (S_THth(n->suffix))
3137  str_numth(s, s, S_TH_TYPE(n->suffix));
3138  s += strlen(s);
3139  break;
3140  case DCH_YY:
3141  case DCH_IY:
3142  sprintf(s, "%0*d",
3143  S_FM(n->suffix) ? 0 :
3144  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
3145  (n->key->id == DCH_YY ?
3146  ADJUST_YEAR(tm->tm_year, is_interval) :
3148  tm->tm_mon,
3149  tm->tm_mday),
3150  is_interval)) % 100);
3151  if (S_THth(n->suffix))
3152  str_numth(s, s, S_TH_TYPE(n->suffix));
3153  s += strlen(s);
3154  break;
3155  case DCH_Y:
3156  case DCH_I:
3157  sprintf(s, "%1d",
3158  (n->key->id == DCH_Y ?
3159  ADJUST_YEAR(tm->tm_year, is_interval) :
3161  tm->tm_mon,
3162  tm->tm_mday),
3163  is_interval)) % 10);
3164  if (S_THth(n->suffix))
3165  str_numth(s, s, S_TH_TYPE(n->suffix));
3166  s += strlen(s);
3167  break;
3168  case DCH_RM:
3169  /* FALLTHROUGH */
3170  case DCH_rm:
3171 
3172  /*
3173  * For intervals, values like '12 month' will be reduced to 0
3174  * month and some years. These should be processed.
3175  */
3176  if (!tm->tm_mon && !tm->tm_year)
3177  break;
3178  else
3179  {
3180  int mon = 0;
3181  const char *const *months;
3182 
3183  if (n->key->id == DCH_RM)
3185  else
3187 
3188  /*
3189  * Compute the position in the roman-numeral array. Note
3190  * that the contents of the array are reversed, December
3191  * being first and January last.
3192  */
3193  if (tm->tm_mon == 0)
3194  {
3195  /*
3196  * This case is special, and tracks the case of full
3197  * interval years.
3198  */
3199  mon = tm->tm_year >= 0 ? 0 : MONTHS_PER_YEAR - 1;
3200  }
3201  else if (tm->tm_mon < 0)
3202  {
3203  /*
3204  * Negative case. In this case, the calculation is
3205  * reversed, where -1 means December, -2 November,
3206  * etc.
3207  */
3208  mon = -1 * (tm->tm_mon + 1);
3209  }
3210  else
3211  {
3212  /*
3213  * Common case, with a strictly positive value. The
3214  * position in the array matches with the value of
3215  * tm_mon.
3216  */
3217  mon = MONTHS_PER_YEAR - tm->tm_mon;
3218  }
3219 
3220  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
3221  months[mon]);
3222  s += strlen(s);
3223  }
3224  break;
3225  case DCH_W:
3226  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
3227  if (S_THth(n->suffix))
3228  str_numth(s, s, S_TH_TYPE(n->suffix));
3229  s += strlen(s);
3230  break;
3231  case DCH_J:
3232  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
3233  if (S_THth(n->suffix))
3234  str_numth(s, s, S_TH_TYPE(n->suffix));
3235  s += strlen(s);
3236  break;
3237  }
3238  }
3239 
3240  *s = '\0';
3241 }
int date2j(int year, int month, int day)
Definition: datetime.c:288
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:5097
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:5209
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:5152
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define SECS_PER_MINUTE
Definition: timestamp.h:128
#define HOURS_PER_DAY
Definition: timestamp.h:118
#define ereport(elevel,...)
Definition: elog.h:149
#define ad_STR
Definition: formatting.c:198
#define bc_STR
Definition: formatting.c:203
#define AD_STR
Definition: formatting.c:197
static char * asc_tolower_z(const char *buff)
Definition: formatting.c:2099
static char * str_numth(char *dest, char *num, int type)
Definition: formatting.c:1550
#define a_d_STR
Definition: formatting.c:196
#define DCH_to_char_fsec(frac_fmt, frac_val)
#define PM_STR
Definition: formatting.c:229
#define BC_STR
Definition: formatting.c:202
#define a_m_STR
Definition: formatting.c:223
#define A_D_STR
Definition: formatting.c:195
static char * str_initcap_z(const char *buff, Oid collid)
Definition: formatting.c:2093
#define pm_STR
Definition: formatting.c:230
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:2081
#define B_C_STR
Definition: formatting.c:200
#define ADJUST_YEAR(year, is_interval)
Definition: formatting.c:193
static char * str_toupper_z(const char *buff, Oid collid)
Definition: formatting.c:2087
#define TM_SUFFIX_LEN
Definition: formatting.c:555
#define b_c_STR
Definition: formatting.c:201
#define INVALID_FOR_INTERVAL
Definition: formatting.c:514
#define S_FM(_s)
Definition: formatting.c:547
#define tmtcTzn(_X)
Definition: formatting.c:479
static char * asc_toupper_z(const char *buff)
Definition: formatting.c:2105
#define P_M_STR
Definition: formatting.c:227
#define p_m_STR
Definition: formatting.c:228
#define A_M_STR
Definition: formatting.c:222
#define am_STR
Definition: formatting.c:225
#define AM_STR
Definition: formatting.c:224
static const char *const rm_months_upper[]
Definition: formatting.c:251
static struct pg_tm tm
Definition: localtime.c:104
int len
Definition: formatting.c:146
struct fmt_tm tm
Definition: formatting.c:473
fsec_t fsec
Definition: formatting.c:474
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_yday
Definition: pgtime.h:43
int tm_wday
Definition: pgtime.h:42
int tm_sec
Definition: pgtime.h:36
long int tm_gmtoff
Definition: pgtime.h:45
int tm_year
Definition: pgtime.h:41

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

◆ do_to_timestamp()

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

Definition at line 4453 of file formatting.c.

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

References Assert(), TmFromChar::bc, TmFromChar::cc, TmFromChar::clock, CLOCK_12_HOUR, collid, TmFromChar::d, DateTimeParseError(), DAY, DCH_cache_fetch(), DCH_CACHE_SIZE, DCH_datetime_type(), DCH_FLAG, DCH_from_char(), DCH_index, DCH_keywords, DCH_suff, TmFromChar::dd, TmFromChar::ddd, DEBUG_TM, DEBUG_TMFC, DTERR_FIELD_OVERFLOW, DTERR_TZDISP_OVERFLOW, DTK_DATE_M, DTK_M, errcode(), errhint(), errmsg(), errsave, TmFromChar::ff, fmt, DCHCacheEntry::format, 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(), SECS_PER_HOUR, SECS_PER_MINUTE, SOFT_ERROR_OCCURRED, TmFromChar::ss, TmFromChar::ssss, STD_FLAG, text_to_cstring(), tm, 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, x, y, TmFromChar::year, YEAR, TmFromChar::yysz, ZERO_tm, and ZERO_tmfc.

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

◆ fill_str()

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

Definition at line 4789 of file formatting.c.

4790 {
4791  memset(str, c, max);
4792  *(str + max) = '\0';
4793  return str;
4794 }

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

◆ float4_to_char()

Datum float4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6474 of file formatting.c.

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

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

◆ float8_to_char()

Datum float8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6576 of file formatting.c.

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

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

◆ from_char_parse_int()

static int from_char_parse_int ( int *  dest,
const char **  src,
FormatNode node,
Node escontext 
)
static

Definition at line 2406 of file formatting.c.

2408 {
2409  return from_char_parse_int_len(dest, src, node->key->len, node, escontext);
2410 }

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

Referenced by DCH_from_char().

◆ from_char_parse_int_len()

static int from_char_parse_int_len ( int *  dest,
const char **  src,
const int  len,
FormatNode node,
Node escontext 
)
static

Definition at line 2309 of file formatting.c.

2311 {
2312  long result;
2313  char copy[DCH_MAX_ITEM_SIZ + 1];
2314  const char *init = *src;
2315  int used;
2316 
2317  /*
2318  * Skip any whitespace before parsing the integer.
2319  */
2320  *src += strspace_len(*src);
2321 
2323  used = (int) strlcpy(copy, *src, len + 1);
2324 
2325  if (S_FM(node->suffix) || is_next_separator(node))
2326  {
2327  /*
2328  * This node is in Fill Mode, or the next node is known to be a
2329  * non-digit value, so we just slurp as many characters as we can get.
2330  */
2331  char *endptr;
2332 
2333  errno = 0;
2334  result = strtol(init, &endptr, 10);
2335  *src = endptr;
2336  }
2337  else
2338  {
2339  /*
2340  * We need to pull exactly the number of characters given in 'len' out
2341  * of the string, and convert those.
2342  */
2343  char *last;
2344 
2345  if (used < len)
2346  ereturn(escontext, -1,
2347  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2348  errmsg("source string too short for \"%s\" formatting field",
2349  node->key->name),
2350  errdetail("Field requires %d characters, but only %d remain.",
2351  len, used),
2352  errhint("If your source string is not fixed-width, "
2353  "try using the \"FM\" modifier.")));
2354 
2355  errno = 0;
2356  result = strtol(copy, &last, 10);
2357  used = last - copy;
2358 
2359  if (used > 0 && used < len)
2360  ereturn(escontext, -1,
2361  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2362  errmsg("invalid value \"%s\" for \"%s\"",
2363  copy, node->key->name),
2364  errdetail("Field requires %d characters, but only %d could be parsed.",
2365  len, used),
2366  errhint("If your source string is not fixed-width, "
2367  "try using the \"FM\" modifier.")));
2368 
2369  *src += used;
2370  }
2371 
2372  if (*src == init)
2373  ereturn(escontext, -1,
2374  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2375  errmsg("invalid value \"%s\" for \"%s\"",
2376  copy, node->key->name),
2377  errdetail("Value must be an integer.")));
2378 
2379  if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2380  ereturn(escontext, -1,
2381  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2382  errmsg("value for \"%s\" in source string is out of range",
2383  node->key->name),
2384  errdetail("Value must be in the range %d to %d.",
2385  INT_MIN, INT_MAX)));
2386 
2387  if (dest != NULL)
2388  {
2389  if (!from_char_set_int(dest, (int) result, node, escontext))
2390  return -1;
2391  }
2392 
2393  return *src - init;
2394 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
static bool is_next_separator(FormatNode *n)
Definition: formatting.c:2167
static int strspace_len(const char *str)
Definition: formatting.c:2224
int init
Definition: isn.c:75

References Assert(), DCH_MAX_ITEM_SIZ, generate_unaccent_rules::dest, ereturn, errcode(), errdetail(), errhint(), errmsg(), from_char_set_int(), init, is_next_separator(), FormatNode::key, len, KeyWord::name, S_FM, strlcpy(), strspace_len(), and FormatNode::suffix.

Referenced by DCH_from_char(), and from_char_parse_int().

◆ from_char_seq_search()

static bool from_char_seq_search ( int *  dest,
const char **  src,
const char *const *  array,
char **  localized_array,
Oid  collid,
FormatNode node,
Node escontext 
)
static

Definition at line 2565 of file formatting.c.

2568 {
2569  int len;
2570 
2571  if (localized_array == NULL)
2572  *dest = seq_search_ascii(*src, array, &len);
2573  else
2574  *dest = seq_search_localized(*src, localized_array, &len, collid);
2575 
2576  if (len <= 0)
2577  {
2578  /*
2579  * In the error report, truncate the string at the next whitespace (if
2580  * any) to avoid including irrelevant data.
2581  */
2582  char *copy = pstrdup(*src);
2583  char *c;
2584 
2585  for (c = copy; *c; c++)
2586  {
2587  if (scanner_isspace(*c))
2588  {
2589  *c = '\0';
2590  break;
2591  }
2592  }
2593 
2594  ereturn(escontext, false,
2595  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2596  errmsg("invalid value \"%s\" for \"%s\"",
2597  copy, node->key->name),
2598  errdetail("The given value did not match any of "
2599  "the allowed values for this field.")));
2600  }
2601  *src += len;
2602  return true;
2603 }
static int seq_search_localized(const char *name, char **array, int *len, Oid collid)
Definition: formatting.c:2481
static int seq_search_ascii(const char *name, const char *const *array, int *len)
Definition: formatting.c:2424
char * pstrdup(const char *in)
Definition: mcxt.c:1644
bool scanner_isspace(char ch)
Definition: scansup.c:117

References collid, generate_unaccent_rules::dest, ereturn, errcode(), errdetail(), errmsg(), FormatNode::key, len, KeyWord::name, pstrdup(), scanner_isspace(), seq_search_ascii(), and seq_search_localized().

Referenced by DCH_from_char().

◆ from_char_set_int()

static bool from_char_set_int ( int *  dest,
const int  value,
const FormatNode node,
Node escontext 
)
static

Definition at line 2273 of file formatting.c.

2275 {
2276  if (*dest != 0 && *dest != value)
2277  ereturn(escontext, false,
2278  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2279  errmsg("conflicting values for \"%s\" field in formatting string",
2280  node->key->name),
2281  errdetail("This value contradicts a previous setting "
2282  "for the same field type.")));
2283  *dest = value;
2284  return true;
2285 }

References generate_unaccent_rules::dest, ereturn, errcode(), errdetail(), errmsg(), FormatNode::key, KeyWord::name, and value.

Referenced by DCH_from_char(), and from_char_parse_int_len().

◆ from_char_set_mode()

static bool from_char_set_mode ( TmFromChar tmfc,
const FromCharDateMode  mode,
Node escontext 
)
static

Definition at line 2246 of file formatting.c.

2248 {
2249  if (mode != FROM_CHAR_DATE_NONE)
2250  {
2251  if (tmfc->mode == FROM_CHAR_DATE_NONE)
2252  tmfc->mode = mode;
2253  else if (tmfc->mode != mode)
2254  ereturn(escontext, false,
2255  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2256  errmsg("invalid combination of date conventions"),
2257  errhint("Do not mix Gregorian and ISO week date "
2258  "conventions in a formatting template.")));
2259  }
2260  return true;
2261 }
static PgChecksumMode mode
Definition: pg_checksums.c:56

References ereturn, errcode(), errhint(), errmsg(), FROM_CHAR_DATE_NONE, TmFromChar::mode, and mode.

Referenced by DCH_from_char().

◆ get_last_relevant_decnum()

static char * get_last_relevant_decnum ( char *  num)
static

Definition at line 5120 of file formatting.c.

5121 {
5122  char *result,
5123  *p = strchr(num, '.');
5124 
5125 #ifdef DEBUG_TO_FROM_CHAR
5126  elog(DEBUG_elog_output, "get_last_relevant_decnum()");
5127 #endif
5128 
5129  if (!p)
5130  return NULL;
5131 
5132  result = p;
5133 
5134  while (*(++p))
5135  {
5136  if (*p != '0')
5137  result = p;
5138  }
5139 
5140  return result;
5141 }

References elog().

Referenced by NUM_processor().

◆ get_th()

static const char * get_th ( char *  num,
int  type 
)
static

Definition at line 1505 of file formatting.c.

1506 {
1507  int len = strlen(num),
1508  last;
1509 
1510  last = *(num + (len - 1));
1511  if (!isdigit((unsigned char) last))
1512  ereport(ERROR,
1513  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1514  errmsg("\"%s\" is not a number", num)));
1515 
1516  /*
1517  * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
1518  * 'ST/st', 'ND/nd', 'RD/rd', respectively
1519  */
1520  if ((len > 1) && (num[len - 2] == '1'))
1521  last = 0;
1522 
1523  switch (last)
1524  {
1525  case '1':
1526  if (type == TH_UPPER)
1527  return numTH[0];
1528  return numth[0];
1529  case '2':
1530  if (type == TH_UPPER)
1531  return numTH[1];
1532  return numth[1];
1533  case '3':
1534  if (type == TH_UPPER)
1535  return numTH[2];
1536  return numth[2];
1537  default:
1538  if (type == TH_UPPER)
1539  return numTH[3];
1540  return numth[3];
1541  }
1542 }
static const char *const numth[]
Definition: formatting.c:270
static const char *const numTH[]
Definition: formatting.c:269
#define TH_UPPER
Definition: formatting.c:276
const char * type

References ereport, errcode(), errmsg(), ERROR, len, numTH, numth, TH_UPPER, and type.

Referenced by NUM_processor(), and str_numth().

◆ index_seq_search()

static const KeyWord * index_seq_search ( const char *  str,
const KeyWord kw,
const int *  index 
)
static

Definition at line 1088 of file formatting.c.

1089 {
1090  int poz;
1091 
1092  if (!KeyWord_INDEX_FILTER(*str))
1093  return NULL;
1094 
1095  if ((poz = *(index + (*str - ' '))) > -1)
1096  {
1097  const KeyWord *k = kw + poz;
1098 
1099  do
1100  {
1101  if (strncmp(str, k->name, k->len) == 0)
1102  return k;
1103  k++;
1104  if (!k->name)
1105  return NULL;
1106  } while (*str == *k->name);
1107  }
1108  return NULL;
1109 }
#define KeyWord_INDEX_FILTER(_c)
Definition: formatting.c:107
Definition: type.h:95

References KeyWord_INDEX_FILTER, KeyWord::len, KeyWord::name, and generate_unaccent_rules::str.

Referenced by parse_format().

◆ int4_to_char()

Datum int4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6274 of file formatting.c.

6279 {
6281  text *fmt = PG_GETARG_TEXT_PP(1);
6282  NUMDesc Num;
6283  FormatNode *format;
6284  text *result;
6285  bool shouldFree;
6286  int out_pre_spaces = 0,
6287  sign = 0;
6288  char *numstr,
6289  *orgnum;
6290 
6292 
6293  /*
6294  * On DateType depend part (int32)
6295  */
6296  if (IS_ROMAN(&Num))
6297  numstr = int_to_roman(value);
6298  else if (IS_EEEE(&Num))
6299  {
6300  /* we can do it easily because float8 won't lose any precision */
6301  float8 val = (float8) value;
6302 
6303  orgnum = (char *) psprintf("%+.*e", Num.post, val);
6304 
6305  /*
6306  * Swap a leading positive sign for a space.
6307  */
6308  if (*orgnum == '+')
6309  *orgnum = ' ';
6310 
6311  numstr = orgnum;
6312  }
6313  else
6314  {
6315  int numstr_pre_len;
6316 
6317  if (IS_MULTI(&Num))
6318  {
6320  Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
6321  Num.pre += Num.multi;
6322  }
6323  else
6324  {
6326  Int32GetDatum(value)));
6327  }
6328 
6329  if (*orgnum == '-')
6330  {
6331  sign = '-';
6332  orgnum++;
6333  }
6334  else
6335  sign = '+';
6336 
6337  numstr_pre_len = strlen(orgnum);
6338 
6339  /* post-decimal digits? Pad out with zeros. */
6340  if (Num.post)
6341  {
6342  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6343  strcpy(numstr, orgnum);
6344  *(numstr + numstr_pre_len) = '.';
6345  memset(numstr + numstr_pre_len + 1, '0', Num.post);
6346  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6347  }
6348  else
6349  numstr = orgnum;
6350 
6351  /* needs padding? */
6352  if (numstr_pre_len < Num.pre)
6353  out_pre_spaces = Num.pre - numstr_pre_len;
6354  /* overflowed prefix digit format? */
6355  else if (numstr_pre_len > Num.pre)
6356  {
6357  numstr = (char *) palloc(Num.pre + Num.post + 2);
6358  fill_str(numstr, '#', Num.pre + Num.post + 1);
6359  *(numstr + Num.pre) = '.';
6360  }
6361  }
signed int int32
Definition: c.h:483
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
Datum int4out(PG_FUNCTION_ARGS)
Definition: int.c:298
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

References DatumGetCString(), DirectFunctionCall1, fill_str(), fmt, format, Int32GetDatum(), int4out(), int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, NUMDesc::multi, NUM_TOCHAR_finish, NUM_TOCHAR_prepare, palloc(), PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, psprintf(), sign, val, and value.

◆ int8_to_char()

Datum int8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 6368 of file formatting.c.

6373 {
6374  int64 value = PG_GETARG_INT64(0);
6375  text *fmt = PG_GETARG_TEXT_PP(1);
6376  NUMDesc Num;
6377  FormatNode *format;
6378  text *result;
6379  bool shouldFree;
6380  int out_pre_spaces = 0,
6381  sign = 0;
6382  char *numstr,
6383  *orgnum;
6384 
6386 
6387  /*
6388  * On DateType depend part (int32)
6389  */
6390  if (IS_ROMAN(&Num))
6391  {
6392  /* Currently don't support int8 conversion to roman... */
6394  }
6395  else if (IS_EEEE(&Num))
6396  {
6397  /* to avoid loss of precision, must go via numeric not float8 */
6399  Num.post);
6400 
6401  /*
6402  * numeric_out_sci() does not emit a sign for positive numbers. We
6403  * need to add a space in this case so that positive and negative
6404  * numbers are aligned. We don't have to worry about NaN/inf here.
6405  */
6406  if (*orgnum != '-')
6407  {
6408  numstr = (char *) palloc(strlen(orgnum) + 2);
6409  *numstr = ' ';
6410  strcpy(numstr + 1, orgnum);
6411  }
6412  else
6413  {
6414  numstr = orgnum;
6415  }
6416  }
6417  else
6418  {
6419  int numstr_pre_len;
6420 
6421  if (IS_MULTI(&Num))
6422  {
6423  double multi = pow((double) 10, (double) Num.multi);
6424 
6428  Float8GetDatum(multi))));
6429  Num.pre += Num.multi;
6430  }
6431 
6433  Int64GetDatum(value)));
6434 
6435  if (*orgnum == '-')
6436  {
6437  sign = '-';
6438  orgnum++;
6439  }
6440  else
6441  sign = '+';
6442 
6443  numstr_pre_len = strlen(orgnum);
6444 
6445  /* post-decimal digits? Pad out with zeros. */
6446  if (Num.post)
6447  {
6448  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6449  strcpy(numstr, orgnum);
6450  *(numstr + numstr_pre_len) = '.';
6451  memset(numstr + numstr_pre_len + 1, '0', Num.post);
6452  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6453  }
6454  else
6455  numstr = orgnum;
6456 
6457  /* needs padding? */
6458  if (numstr_pre_len < Num.pre)
6459  out_pre_spaces = Num.pre - numstr_pre_len;
6460  /* overflowed prefix digit format? */
6461  else if (numstr_pre_len > Num.pre)
6462  {
6463  numstr = (char *) palloc(Num.pre + Num.post + 2);
6464  fill_str(numstr, '#', Num.pre + Num.post + 1);
6465  *(numstr + Num.pre) = '.';
6466  }
6467  }
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4232
char * numeric_out_sci(Numeric num, int scale)
Definition: numeric.c:982
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1790
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1799
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
Datum int8out(PG_FUNCTION_ARGS)
Definition: int8.c:62
Datum int84(PG_FUNCTION_ARGS)
Definition: int8.c:1250
Datum int8mul(PG_FUNCTION_ARGS)
Definition: int8.c:491
Datum dtoi8(PG_FUNCTION_ARGS)
Definition: int8.c:1298
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202

References DatumGetCString(), DatumGetInt32(), DatumGetInt64(), DirectFunctionCall1, DirectFunctionCall2, dtoi8(), fill_str(), Float8GetDatum(), fmt, format, int64_to_numeric(), Int64GetDatum(), int84(), int8mul(), int8out(), int_to_roman(), IS_EEEE, IS_MULTI, IS_ROMAN, NUMDesc::multi, NUM_TOCHAR_finish, NUM_TOCHAR_prepare, numeric_out_sci(), palloc(), PG_GETARG_INT64, PG_GETARG_TEXT_PP, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, sign, and value.

◆ int_to_roman()

static char * int_to_roman ( int  number)
static

Definition at line 4989 of file formatting.c.

4990 {
4991  int len,
4992  num;
4993  char *p,
4994  *result,
4995  numstr[12];
4996 
4997  result = (char *) palloc(16);
4998  *result = '\0';
4999 
5000  if (number > 3999 || number < 1)
5001  {
5002  fill_str(result, '#', 15);
5003  return result;
5004  }
5005  len = snprintf(numstr, sizeof(numstr), "%d", number);
5006 
5007  for (p = numstr; *p != '\0'; p++, --len)
5008  {
5009  num = *p - ('0' + 1);
5010  if (num < 0)
5011  continue;
5012 
5013  if (len > 3)
5014  {
5015  while (num-- != -1)
5016  strcat(result, "M");
5017  }
5018  else
5019  {
5020  if (len == 3)
5021  strcat(result, rm100[num]);
5022  else if (len == 2)
5023  strcat(result, rm10[num]);
5024  else if (len == 1)
5025  strcat(result, rm1[num]);
5026  }
5027  }
5028  return result;
5029 }
static const char *const rm100[]
Definition: formatting.c:263
static const char *const rm10[]
Definition: formatting.c:262
static const char *const rm1[]
Definition: formatting.c:261
#define snprintf
Definition: port.h:238

References fill_str(), len, palloc(), rm1, rm10, rm100, and snprintf.

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

◆ interval_to_char()

Datum interval_to_char ( PG_FUNCTION_ARGS  )

Definition at line 4120 of file formatting.c.

4121 {
4122  Interval *it = PG_GETARG_INTERVAL_P(0);
4123  text *fmt = PG_GETARG_TEXT_PP(1),
4124  *res;
4125  TmToChar tmtc;
4126  struct fmt_tm *tm;
4127  struct pg_itm tt,
4128  *itm = &tt;
4129 
4130  if (VARSIZE_ANY_EXHDR(fmt) <= 0 || INTERVAL_NOT_FINITE(it))
4131  PG_RETURN_NULL();
4132 
4133  ZERO_tmtc(&tmtc);
4134  tm = tmtcTm(&tmtc);
4135 
4136  interval2itm(*it, itm);
4137  tmtc.fsec = itm->tm_usec;
4138  tm->tm_sec = itm->tm_sec;
4139  tm->tm_min = itm->tm_min;
4140  tm->tm_hour = itm->tm_hour;
4141  tm->tm_mday = itm->tm_mday;
4142  tm->tm_mon = itm->tm_mon;
4143  tm->tm_year = itm->tm_year;
4144 
4145  /* wday is meaningless, yday approximates the total span in days */
4147 
4148  if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
4149  PG_RETURN_NULL();
4150 
4152 }
void interval2itm(Interval span, struct pg_itm *itm)
Definition: timestamp.c:2042
#define INTERVAL_NOT_FINITE(i)
Definition: timestamp.h:195
#define DAYS_PER_MONTH
Definition: timestamp.h:116
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
static text * datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
Definition: formatting.c:3975
#define ZERO_tmtc(_X)
Definition: formatting.c:503
int64 tm_hour
Definition: timestamp.h:70
int tm_year
Definition: timestamp.h:73
int tm_mon
Definition: timestamp.h:72
int tm_mday
Definition: timestamp.h:71
int tm_sec
Definition: timestamp.h:68
int tm_min
Definition: timestamp.h:69
int tm_usec
Definition: timestamp.h:67
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:65

References datetime_to_char_body(), DAYS_PER_MONTH, fmt, TmToChar::fsec, if(), interval2itm(), INTERVAL_NOT_FINITE, MONTHS_PER_YEAR, PG_GET_COLLATION, PG_GETARG_INTERVAL_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, res, tm, pg_itm::tm_hour, pg_tm::tm_hour, pg_itm::tm_mday, pg_tm::tm_mday, pg_itm::tm_min, pg_tm::tm_min, pg_itm::tm_mon, pg_tm::tm_mon, pg_itm::tm_sec, pg_tm::tm_sec, pg_itm::tm_usec, pg_tm::tm_yday, pg_itm::tm_year, pg_tm::tm_year, tmtcTm, VARSIZE_ANY_EXHDR, and ZERO_tmtc.

◆ is_next_separator()

static bool is_next_separator ( FormatNode n)
static

Definition at line 2167 of file formatting.c.

2168 {
2169  if (n->type == NODE_TYPE_END)
2170  return false;
2171 
2172  if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
2173  return true;
2174 
2175  /*
2176  * Next node