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 5167 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 5378 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:676
#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:5592
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 6089 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:4949
static void const char * fmt
void * palloc0(Size size)
Definition: mcxt.c:1257
Definition: c.h:671
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:182

Definition at line 6076 of file formatting.c.

◆ OVERLOAD_TEST

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

Definition at line 5166 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 2137 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 4814 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 2218 of file formatting.c.

2219 {
2220  /*
2221  * Adjust all dates toward 2020; this is effectively what happens when we
2222  * assume '70' is 1970 and '69' is 2069.
2223  */
2224  /* Force 0-69 into the 2000's */
2225  if (year < 70)
2226  return year + 2000;
2227  /* Force 70-99 into the 1900's */
2228  else if (year < 100)
2229  return year + 1900;
2230  /* Force 100-519 into the 2000's */
2231  else if (year < 520)
2232  return year + 2000;
2233  /* Force 520-999 into the 1000's */
2234  else if (year < 1000)
2235  return year + 1000;
2236  else
2237  return year;
2238 }

Referenced by DCH_from_char().

◆ asc_initcap()

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

Definition at line 2068 of file formatting.c.

2069 {
2070  char *result;
2071  char *p;
2072  int wasalnum = false;
2073 
2074  if (!buff)
2075  return NULL;
2076 
2077  result = pnstrdup(buff, nbytes);
2078 
2079  for (p = result; *p; p++)
2080  {
2081  char c;
2082 
2083  if (wasalnum)
2084  *p = c = pg_ascii_tolower((unsigned char) *p);
2085  else
2086  *p = c = pg_ascii_toupper((unsigned char) *p);
2087  /* we don't trust isalnum() here */
2088  wasalnum = ((c >= 'A' && c <= 'Z') ||
2089  (c >= 'a' && c <= 'z') ||
2090  (c >= '0' && c <= '9'));
2091  }
2092 
2093  return result;
2094 }
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 2022 of file formatting.c.

2023 {
2024  char *result;
2025  char *p;
2026 
2027  if (!buff)
2028  return NULL;
2029 
2030  result = pnstrdup(buff, nbytes);
2031 
2032  for (p = result; *p; p++)
2033  *p = pg_ascii_tolower((unsigned char) *p);
2034 
2035  return result;
2036 }

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

2118 {
2119  return asc_tolower(buff, strlen(buff));
2120 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:2022

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

2046 {
2047  char *result;
2048  char *p;
2049 
2050  if (!buff)
2051  return NULL;
2052 
2053  result = pnstrdup(buff, nbytes);
2054 
2055  for (p = result; *p; p++)
2056  *p = pg_ascii_toupper((unsigned char) *p);
2057 
2058  return result;
2059 }

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

2124 {
2125  return asc_toupper(buff, strlen(buff));
2126 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:2045

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

3994 {
3995  FormatNode *format;
3996  char *fmt_str,
3997  *result;
3998  bool incache;
3999  int fmt_len;
4000  text *res;
4001 
4002  /*
4003  * Convert fmt to C string
4004  */
4005  fmt_str = text_to_cstring(fmt);
4006  fmt_len = strlen(fmt_str);
4007 
4008  /*
4009  * Allocate workspace for result as C string
4010  */
4011  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
4012  *result = '\0';
4013 
4014  if (fmt_len > DCH_CACHE_SIZE)
4015  {
4016  /*
4017  * Allocate new memory if format picture is bigger than static cache
4018  * and do not use cache (call parser always)
4019  */
4020  incache = false;
4021 
4022  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
4023 
4024  parse_format(format, fmt_str, DCH_keywords,
4025  DCH_suff, DCH_index, DCH_FLAG, NULL);
4026  }
4027  else
4028  {
4029  /*
4030  * Use cache buffers
4031  */
4032  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
4033 
4034  incache = true;
4035  format = ent->format;
4036  }
4037 
4038  /* The real work is here */
4039  DCH_to_char(format, is_interval, tmtc, result, collid);
4040 
4041  if (!incache)
4042  pfree(format);
4043 
4044  pfree(fmt_str);
4045 
4046  /* convert C-string result to TEXT format */
4047  res = cstring_to_text(result);
4048 
4049  pfree(result);
4050  return res;
4051 }
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:2629
#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:3966
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:215

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

3967 {
3968  DCHCacheEntry *ent;
3969 
3970  if ((ent = DCH_cache_search(str, std)) == NULL)
3971  {
3972  /*
3973  * Not in the cache, must run parser and save a new format-picture to
3974  * the cache. Do not mark the cache entry valid until parsing
3975  * succeeds.
3976  */
3977  ent = DCH_cache_getnew(str, std);
3978 
3980  DCH_FLAG | (std ? STD_FLAG : 0), NULL);
3981 
3982  ent->valid = true;
3983  }
3984  return ent;
3985 }
#define STD_FLAG
Definition: formatting.c:100
static DCHCacheEntry * DCH_cache_getnew(const char *str, bool std)
Definition: formatting.c:3885
static DCHCacheEntry * DCH_cache_search(const char *str, bool std)
Definition: formatting.c:3945

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

3886 {
3887  DCHCacheEntry *ent;
3888 
3889  /* Ensure we can advance DCHCounter below */
3891 
3892  /*
3893  * If cache is full, remove oldest entry (or recycle first not-valid one)
3894  */
3896  {
3897  DCHCacheEntry *old = DCHCache[0];
3898 
3899 #ifdef DEBUG_TO_FROM_CHAR
3900  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3901 #endif
3902  if (old->valid)
3903  {
3904  for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
3905  {
3906  ent = DCHCache[i];
3907  if (!ent->valid)
3908  {
3909  old = ent;
3910  break;
3911  }
3912  if (ent->age < old->age)
3913  old = ent;
3914  }
3915  }
3916 #ifdef DEBUG_TO_FROM_CHAR
3917  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3918 #endif
3919  old->valid = false;
3920  strlcpy(old->str, str, DCH_CACHE_SIZE + 1);
3921  old->age = (++DCHCounter);
3922  /* caller is expected to fill format, then set valid */
3923  return old;
3924  }
3925  else
3926  {
3927 #ifdef DEBUG_TO_FROM_CHAR
3928  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3929 #endif
3930  Assert(DCHCache[n_DCHCache] == NULL);
3931  DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
3933  ent->valid = false;
3934  strlcpy(ent->str, str, DCH_CACHE_SIZE + 1);
3935  ent->std = std;
3936  ent->age = (++DCHCounter);
3937  /* caller is expected to fill format, then set valid */
3938  ++n_DCHCache;
3939  return ent;
3940  }
3941 }
static void DCH_prevent_counter_overflow(void)
Definition: formatting.c:3774
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 3945 of file formatting.c.

3946 {
3947  /* Ensure we can advance DCHCounter below */
3949 
3950  for (int i = 0; i < n_DCHCache; i++)
3951  {
3952  DCHCacheEntry *ent = DCHCache[i];
3953 
3954  if (ent->valid && strcmp(ent->str, str) == 0 && ent->std == std)
3955  {
3956  ent->age = (++DCHCounter);
3957  return ent;
3958  }
3959  }
3960 
3961  return NULL;
3962 }

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

3789 {
3790  FormatNode *n;
3791  int flags = 0;
3792 
3793  for (n = node; n->type != NODE_TYPE_END; n++)
3794  {
3795  if (n->type != NODE_TYPE_ACTION)
3796  continue;
3797 
3798  switch (n->key->id)
3799  {
3800  case DCH_FX:
3801  break;
3802  case DCH_A_M:
3803  case DCH_P_M:
3804  case DCH_a_m:
3805  case DCH_p_m:
3806  case DCH_AM:
3807  case DCH_PM:
3808  case DCH_am:
3809  case DCH_pm:
3810  case DCH_HH:
3811  case DCH_HH12:
3812  case DCH_HH24:
3813  case DCH_MI:
3814  case DCH_SS:
3815  case DCH_MS: /* millisecond */
3816  case DCH_US: /* microsecond */
3817  case DCH_FF1:
3818  case DCH_FF2:
3819  case DCH_FF3:
3820  case DCH_FF4:
3821  case DCH_FF5:
3822  case DCH_FF6:
3823  case DCH_SSSS:
3824  flags |= DCH_TIMED;
3825  break;
3826  case DCH_tz:
3827  case DCH_TZ:
3828  case DCH_OF:
3829  case DCH_TZH:
3830  case DCH_TZM:
3831  flags |= DCH_ZONED;
3832  break;
3833  case DCH_A_D:
3834  case DCH_B_C:
3835  case DCH_a_d:
3836  case DCH_b_c:
3837  case DCH_AD:
3838  case DCH_BC:
3839  case DCH_ad:
3840  case DCH_bc:
3841  case DCH_MONTH:
3842  case DCH_Month:
3843  case DCH_month:
3844  case DCH_MON:
3845  case DCH_Mon:
3846  case DCH_mon:
3847  case DCH_MM:
3848  case DCH_DAY:
3849  case DCH_Day:
3850  case DCH_day:
3851  case DCH_DY:
3852  case DCH_Dy:
3853  case DCH_dy:
3854  case DCH_DDD:
3855  case DCH_IDDD:
3856  case DCH_DD:
3857  case DCH_D:
3858  case DCH_ID:
3859  case DCH_WW:
3860  case DCH_Q:
3861  case DCH_CC:
3862  case DCH_Y_YYY:
3863  case DCH_YYYY:
3864  case DCH_IYYY:
3865  case DCH_YYY:
3866  case DCH_IYY:
3867  case DCH_YY:
3868  case DCH_IY:
3869  case DCH_Y:
3870  case DCH_I:
3871  case DCH_RM:
3872  case DCH_rm:
3873  case DCH_W:
3874  case DCH_J:
3875  flags |= DCH_DATED;
3876  break;
3877  }
3878  }
3879 
3880  return flags;
3881 }
#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 3276 of file formatting.c.

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

3775 {
3776  if (DCHCounter >= (INT_MAX - 1))
3777  {
3778  for (int i = 0; i < n_DCHCache; i++)
3779  DCHCache[i]->age >>= 1;
3780  DCHCounter >>= 1;
3781  }
3782 }

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

2630 {
2631  FormatNode *n;
2632  char *s;
2633  struct fmt_tm *tm = &in->tm;
2634  int i;
2635 
2636  /* cache localized days and months */
2638 
2639  s = out;
2640  for (n = node; n->type != NODE_TYPE_END; n++)
2641  {
2642  if (n->type != NODE_TYPE_ACTION)
2643  {
2644  strcpy(s, n->character);
2645  s += strlen(s);
2646  continue;
2647  }
2648 
2649  switch (n->key->id)
2650  {
2651  case DCH_A_M:
2652  case DCH_P_M:
2653  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2654  ? P_M_STR : A_M_STR);
2655  s += strlen(s);
2656  break;
2657  case DCH_AM:
2658  case DCH_PM:
2659  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2660  ? PM_STR : AM_STR);
2661  s += strlen(s);
2662  break;
2663  case DCH_a_m:
2664  case DCH_p_m:
2665  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2666  ? p_m_STR : a_m_STR);
2667  s += strlen(s);
2668  break;
2669  case DCH_am:
2670  case DCH_pm:
2671  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2672  ? pm_STR : am_STR);
2673  s += strlen(s);
2674  break;
2675  case DCH_HH:
2676  case DCH_HH12:
2677 
2678  /*
2679  * display time as shown on a 12-hour clock, even for
2680  * intervals
2681  */
2682  sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2683  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ?
2684  (long long) (HOURS_PER_DAY / 2) :
2685  (long long) (tm->tm_hour % (HOURS_PER_DAY / 2)));
2686  if (S_THth(n->suffix))
2687  str_numth(s, s, S_TH_TYPE(n->suffix));
2688  s += strlen(s);
2689  break;
2690  case DCH_HH24:
2691  sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2692  (long long) tm->tm_hour);
2693  if (S_THth(n->suffix))
2694  str_numth(s, s, S_TH_TYPE(n->suffix));
2695  s += strlen(s);
2696  break;
2697  case DCH_MI:
2698  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2699  tm->tm_min);
2700  if (S_THth(n->suffix))
2701  str_numth(s, s, S_TH_TYPE(n->suffix));
2702  s += strlen(s);
2703  break;
2704  case DCH_SS:
2705  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2706  tm->tm_sec);
2707  if (S_THth(n->suffix))
2708  str_numth(s, s, S_TH_TYPE(n->suffix));
2709  s += strlen(s);
2710  break;
2711 
2712 #define DCH_to_char_fsec(frac_fmt, frac_val) \
2713  sprintf(s, frac_fmt, (int) (frac_val)); \
2714  if (S_THth(n->suffix)) \
2715  str_numth(s, s, S_TH_TYPE(n->suffix)); \
2716  s += strlen(s)
2717 
2718  case DCH_FF1: /* tenth of second */
2719  DCH_to_char_fsec("%01d", in->fsec / 100000);
2720  break;
2721  case DCH_FF2: /* hundredth of second */
2722  DCH_to_char_fsec("%02d", in->fsec / 10000);
2723  break;
2724  case DCH_FF3:
2725  case DCH_MS: /* millisecond */
2726  DCH_to_char_fsec("%03d", in->fsec / 1000);
2727  break;
2728  case DCH_FF4: /* tenth of a millisecond */
2729  DCH_to_char_fsec("%04d", in->fsec / 100);
2730  break;
2731  case DCH_FF5: /* hundredth of a millisecond */
2732  DCH_to_char_fsec("%05d", in->fsec / 10);
2733  break;
2734  case DCH_FF6:
2735  case DCH_US: /* microsecond */
2736  DCH_to_char_fsec("%06d", in->fsec);
2737  break;
2738 #undef DCH_to_char_fsec
2739  case DCH_SSSS:
2740  sprintf(s, "%lld",
2741  (long long) (tm->tm_hour * SECS_PER_HOUR +
2743  tm->tm_sec));
2744  if (S_THth(n->suffix))
2745  str_numth(s, s, S_TH_TYPE(n->suffix));
2746  s += strlen(s);
2747  break;
2748  case DCH_tz:
2750  if (tmtcTzn(in))
2751  {
2752  /* We assume here that timezone names aren't localized */
2753  char *p = asc_tolower_z(tmtcTzn(in));
2754 
2755  strcpy(s, p);
2756  pfree(p);
2757  s += strlen(s);
2758  }
2759  break;
2760  case DCH_TZ:
2762  if (tmtcTzn(in))
2763  {
2764  strcpy(s, tmtcTzn(in));
2765  s += strlen(s);
2766  }
2767  break;
2768  case DCH_TZH:
2770  sprintf(s, "%c%02d",
2771  (tm->tm_gmtoff >= 0) ? '+' : '-',
2772  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2773  s += strlen(s);
2774  break;
2775  case DCH_TZM:
2777  sprintf(s, "%02d",
2778  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2779  s += strlen(s);
2780  break;
2781  case DCH_OF:
2783  sprintf(s, "%c%0*d",
2784  (tm->tm_gmtoff >= 0) ? '+' : '-',
2785  S_FM(n->suffix) ? 0 : 2,
2786  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2787  s += strlen(s);
2788  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2789  {
2790  sprintf(s, ":%02d",
2791  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2792  s += strlen(s);
2793  }
2794  break;
2795  case DCH_A_D:
2796  case DCH_B_C:
2798  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2799  s += strlen(s);
2800  break;
2801  case DCH_AD:
2802  case DCH_BC:
2804  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2805  s += strlen(s);
2806  break;
2807  case DCH_a_d:
2808  case DCH_b_c:
2810  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2811  s += strlen(s);
2812  break;
2813  case DCH_ad:
2814  case DCH_bc:
2816  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2817  s += strlen(s);
2818  break;
2819  case DCH_MONTH:
2821  if (!tm->tm_mon)
2822  break;
2823  if (S_TM(n->suffix))
2824  {
2826 
2827  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2828  strcpy(s, str);
2829  else
2830  ereport(ERROR,
2831  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2832  errmsg("localized string format value too long")));
2833  }
2834  else
2835  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2837  s += strlen(s);
2838  break;
2839  case DCH_Month:
2841  if (!tm->tm_mon)
2842  break;
2843  if (S_TM(n->suffix))
2844  {
2846 
2847  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2848  strcpy(s, str);
2849  else
2850  ereport(ERROR,
2851  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2852  errmsg("localized string format value too long")));
2853  }
2854  else
2855  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2856  months_full[tm->tm_mon - 1]);
2857  s += strlen(s);
2858  break;
2859  case DCH_month:
2861  if (!tm->tm_mon)
2862  break;
2863  if (S_TM(n->suffix))
2864  {
2866 
2867  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2868  strcpy(s, str);
2869  else
2870  ereport(ERROR,
2871  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2872  errmsg("localized string format value too long")));
2873  }
2874  else
2875  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2877  s += strlen(s);
2878  break;
2879  case DCH_MON:
2881  if (!tm->tm_mon)
2882  break;
2883  if (S_TM(n->suffix))
2884  {
2886 
2887  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2888  strcpy(s, str);
2889  else
2890  ereport(ERROR,
2891  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2892  errmsg("localized string format value too long")));
2893  }
2894  else
2895  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2896  s += strlen(s);
2897  break;
2898  case DCH_Mon:
2900  if (!tm->tm_mon)
2901  break;
2902  if (S_TM(n->suffix))
2903  {
2905 
2906  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2907  strcpy(s, str);
2908  else
2909  ereport(ERROR,
2910  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2911  errmsg("localized string format value too long")));
2912  }
2913  else
2914  strcpy(s, months[tm->tm_mon - 1]);
2915  s += strlen(s);
2916  break;
2917  case DCH_mon:
2919  if (!tm->tm_mon)
2920  break;
2921  if (S_TM(n->suffix))
2922  {
2924 
2925  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2926  strcpy(s, str);
2927  else
2928  ereport(ERROR,
2929  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2930  errmsg("localized string format value too long")));
2931  }
2932  else
2933  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2934  s += strlen(s);
2935  break;
2936  case DCH_MM:
2937  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2938  tm->tm_mon);
2939  if (S_THth(n->suffix))
2940  str_numth(s, s, S_TH_TYPE(n->suffix));
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,
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,
2976  days[tm->tm_wday]);
2977  s += strlen(s);
2978  break;
2979  case DCH_day:
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  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2995  s += strlen(s);
2996  break;
2997  case DCH_DY:
2999  if (S_TM(n->suffix))
3000  {
3002 
3003  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3004  strcpy(s, str);
3005  else
3006  ereport(ERROR,
3007  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3008  errmsg("localized string format value too long")));
3009  }
3010  else
3011  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
3012  s += strlen(s);
3013  break;
3014  case DCH_Dy:
3016  if (S_TM(n->suffix))
3017  {
3019 
3020  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3021  strcpy(s, str);
3022  else
3023  ereport(ERROR,
3024  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3025  errmsg("localized string format value too long")));
3026  }
3027  else
3028  strcpy(s, days_short[tm->tm_wday]);
3029  s += strlen(s);
3030  break;
3031  case DCH_dy:
3033  if (S_TM(n->suffix))
3034  {
3036 
3037  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
3038  strcpy(s, str);
3039  else
3040  ereport(ERROR,
3041  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3042  errmsg("localized string format value too long")));
3043  }
3044  else
3045  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
3046  s += strlen(s);
3047  break;
3048  case DCH_DDD:
3049  case DCH_IDDD:
3050  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
3051  (n->key->id == DCH_DDD) ?
3052  tm->tm_yday :
3054  if (S_THth(n->suffix))
3055  str_numth(s, s, S_TH_TYPE(n->suffix));
3056  s += strlen(s);
3057  break;
3058  case DCH_DD:
3059  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
3060  if (S_THth(n->suffix))
3061  str_numth(s, s, S_TH_TYPE(n->suffix));
3062  s += strlen(s);
3063  break;
3064  case DCH_D:
3066  sprintf(s, "%d", tm->tm_wday + 1);
3067  if (S_THth(n->suffix))
3068  str_numth(s, s, S_TH_TYPE(n->suffix));
3069  s += strlen(s);
3070  break;
3071  case DCH_ID:
3073  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
3074  if (S_THth(n->suffix))
3075  str_numth(s, s, S_TH_TYPE(n->suffix));
3076  s += strlen(s);
3077  break;
3078  case DCH_WW:
3079  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3080  (tm->tm_yday - 1) / 7 + 1);
3081  if (S_THth(n->suffix))
3082  str_numth(s, s, S_TH_TYPE(n->suffix));
3083  s += strlen(s);
3084  break;
3085  case DCH_IW:
3086  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
3088  if (S_THth(n->suffix))
3089  str_numth(s, s, S_TH_TYPE(n->suffix));
3090  s += strlen(s);
3091  break;
3092  case DCH_Q:
3093  if (!tm->tm_mon)
3094  break;
3095  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
3096  if (S_THth(n->suffix))
3097  str_numth(s, s, S_TH_TYPE(n->suffix));
3098  s += strlen(s);
3099  break;
3100  case DCH_CC:
3101  if (is_interval) /* straight calculation */
3102  i = tm->tm_year / 100;
3103  else
3104  {
3105  if (tm->tm_year > 0)
3106  /* Century 20 == 1901 - 2000 */
3107  i = (tm->tm_year - 1) / 100 + 1;
3108  else
3109  /* Century 6BC == 600BC - 501BC */
3110  i = tm->tm_year / 100 - 1;
3111  }
3112  if (i <= 99 && i >= -99)
3113  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
3114  else
3115  sprintf(s, "%d", i);
3116  if (S_THth(n->suffix))
3117  str_numth(s, s, S_TH_TYPE(n->suffix));
3118  s += strlen(s);
3119  break;
3120  case DCH_Y_YYY:
3121  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
3122  sprintf(s, "%d,%03d", i,
3123  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
3124  if (S_THth(n->suffix))
3125  str_numth(s, s, S_TH_TYPE(n->suffix));
3126  s += strlen(s);
3127  break;
3128  case DCH_YYYY:
3129  case DCH_IYYY:
3130  sprintf(s, "%0*d",
3131  S_FM(n->suffix) ? 0 :
3132  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
3133  (n->key->id == DCH_YYYY ?
3134  ADJUST_YEAR(tm->tm_year, is_interval) :
3136  tm->tm_mon,
3137  tm->tm_mday),
3138  is_interval)));
3139  if (S_THth(n->suffix))
3140  str_numth(s, s, S_TH_TYPE(n->suffix));
3141  s += strlen(s);
3142  break;
3143  case DCH_YYY:
3144  case DCH_IYY:
3145  sprintf(s, "%0*d",
3146  S_FM(n->suffix) ? 0 :
3147  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
3148  (n->key->id == DCH_YYY ?
3149  ADJUST_YEAR(tm->tm_year, is_interval) :
3151  tm->tm_mon,
3152  tm->tm_mday),
3153  is_interval)) % 1000);
3154  if (S_THth(n->suffix))
3155  str_numth(s, s, S_TH_TYPE(n->suffix));
3156  s += strlen(s);
3157  break;
3158  case DCH_YY:
3159  case DCH_IY:
3160  sprintf(s, "%0*d",
3161  S_FM(n->suffix) ? 0 :
3162  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
3163  (n->key->id == DCH_YY ?
3164  ADJUST_YEAR(tm->tm_year, is_interval) :
3166  tm->tm_mon,
3167  tm->tm_mday),
3168  is_interval)) % 100);
3169  if (S_THth(n->suffix))
3170  str_numth(s, s, S_TH_TYPE(n->suffix));
3171  s += strlen(s);
3172  break;
3173  case DCH_Y:
3174  case DCH_I:
3175  sprintf(s, "%1d",
3176  (n->key->id == DCH_Y ?
3177  ADJUST_YEAR(tm->tm_year, is_interval) :
3179  tm->tm_mon,
3180  tm->tm_mday),
3181  is_interval)) % 10);
3182  if (S_THth(n->suffix))
3183  str_numth(s, s, S_TH_TYPE(n->suffix));
3184  s += strlen(s);
3185  break;
3186  case DCH_RM:
3187  /* FALLTHROUGH */
3188  case DCH_rm:
3189 
3190  /*
3191  * For intervals, values like '12 month' will be reduced to 0
3192  * month and some years. These should be processed.
3193  */
3194  if (!tm->tm_mon && !tm->tm_year)
3195  break;
3196  else
3197  {
3198  int mon = 0;
3199  const char *const *months;
3200 
3201  if (n->key->id == DCH_RM)
3203  else
3205 
3206  /*
3207  * Compute the position in the roman-numeral array. Note
3208  * that the contents of the array are reversed, December
3209  * being first and January last.
3210  */
3211  if (tm->tm_mon == 0)
3212  {
3213  /*
3214  * This case is special, and tracks the case of full
3215  * interval years.
3216  */
3217  mon = tm->tm_year >= 0 ? 0 : MONTHS_PER_YEAR - 1;
3218  }
3219  else if (tm->tm_mon < 0)
3220  {
3221  /*
3222  * Negative case. In this case, the calculation is
3223  * reversed, where -1 means December, -2 November,
3224  * etc.
3225  */
3226  mon = -1 * (tm->tm_mon + 1);
3227  }
3228  else
3229  {
3230  /*
3231  * Common case, with a strictly positive value. The
3232  * position in the array matches with the value of
3233  * tm_mon.
3234  */
3235  mon = MONTHS_PER_YEAR - tm->tm_mon;
3236  }
3237 
3238  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
3239  months[mon]);
3240  s += strlen(s);
3241  }
3242  break;
3243  case DCH_W:
3244  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
3245  if (S_THth(n->suffix))
3246  str_numth(s, s, S_TH_TYPE(n->suffix));
3247  s += strlen(s);
3248  break;
3249  case DCH_J:
3250  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
3251  if (S_THth(n->suffix))
3252  str_numth(s, s, S_TH_TYPE(n->suffix));
3253  s += strlen(s);
3254  break;
3255  }
3256  }
3257 
3258  *s = '\0';
3259 }
int date2j(int year, int month, int day)
Definition: datetime.c:288
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4510
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:4622
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4565
#define SECS_PER_HOUR
Definition: timestamp.h:126
#define SECS_PER_MINUTE
Definition: timestamp.h:127
#define HOURS_PER_DAY
Definition: timestamp.h:117
#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:2117
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:2111
#define pm_STR
Definition: formatting.c:230
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:2099
#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:2105
#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:2123
#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 4471 of file formatting.c.

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

4808 {
4809  memset(str, c, max);
4810  *(str + max) = '\0';
4811  return str;
4812 }

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

6497 {
6499  text *fmt = PG_GETARG_TEXT_PP(1);
6500  NUMDesc Num;
6501  FormatNode *format;
6502  text *result;
6503  bool shouldFree;
6504  int out_pre_spaces = 0,
6505  sign = 0;
6506  char *numstr,
6507  *p;
6508 
6510 
6511  if (IS_ROMAN(&Num))
6512  numstr = int_to_roman((int) rint(value));
6513  else if (IS_EEEE(&Num))
6514  {
6515  if (isnan(value) || isinf(value))
6516  {
6517  /*
6518  * Allow 6 characters for the leading sign, the decimal point,
6519  * "e", the exponent's sign and two exponent digits.
6520  */
6521  numstr = (char *) palloc(Num.pre + Num.post + 7);
6522  fill_str(numstr, '#', Num.pre + Num.post + 6);
6523  *numstr = ' ';
6524  *(numstr + Num.pre + 1) = '.';
6525  }
6526  else
6527  {
6528  numstr = psprintf("%+.*e", Num.post, value);
6529 
6530  /*
6531  * Swap a leading positive sign for a space.
6532  */
6533  if (*numstr == '+')
6534  *numstr = ' ';
6535  }
6536  }
6537  else
6538  {
6539  float4 val = value;
6540  char *orgnum;
6541  int numstr_pre_len;
6542 
6543  if (IS_MULTI(&Num))
6544  {
6545  float multi = pow((double) 10, (double) Num.multi);
6546 
6547  val = value * multi;
6548  Num.pre += Num.multi;
6549  }
6550 
6551  orgnum = psprintf("%.0f", fabs(val));
6552  numstr_pre_len = strlen(orgnum);
6553 
6554  /* adjust post digits to fit max float digits */
6555  if (numstr_pre_len >= FLT_DIG)
6556  Num.post = 0;
6557  else if (numstr_pre_len + Num.post > FLT_DIG)
6558  Num.post = FLT_DIG - numstr_pre_len;
6559  orgnum = psprintf("%.*f", Num.post, val);
6560 
6561  if (*orgnum == '-')
6562  { /* < 0 */
6563  sign = '-';
6564  numstr = orgnum + 1;
6565  }
6566  else
6567  {
6568  sign = '+';
6569  numstr = orgnum;
6570  }
6571 
6572  if ((p = strchr(numstr, '.')))
6573  numstr_pre_len = p - numstr;
6574  else
6575  numstr_pre_len = strlen(numstr);
6576 
6577  /* needs padding? */
6578  if (numstr_pre_len < Num.pre)
6579  out_pre_spaces = Num.pre - numstr_pre_len;
6580  /* overflowed prefix digit format? */
6581  else if (numstr_pre_len > Num.pre)
6582  {
6583  numstr = (char *) palloc(Num.pre + Num.post + 2);
6584  fill_str(numstr, '#', Num.pre + Num.post + 1);
6585  *(numstr + Num.pre) = '.';
6586  }
6587  }
float float4
Definition: c.h:613
#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:6076
#define IS_MULTI(_f)
Definition: formatting.c:333
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:4807
#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:5007
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 6594 of file formatting.c.

6599 {
6601  text *fmt = PG_GETARG_TEXT_PP(1);
6602  NUMDesc Num;
6603  FormatNode *format;
6604  text *result;
6605  bool shouldFree;
6606  int out_pre_spaces = 0,
6607  sign = 0;
6608  char *numstr,
6609  *p;
6610 
6612 
6613  if (IS_ROMAN(&Num))
6614  numstr = int_to_roman((int) rint(value));
6615  else if (IS_EEEE(&Num))
6616  {
6617  if (isnan(value) || isinf(value))
6618  {
6619  /*
6620  * Allow 6 characters for the leading sign, the decimal point,
6621  * "e", the exponent's sign and two exponent digits.
6622  */
6623  numstr = (char *) palloc(Num.pre + Num.post + 7);
6624  fill_str(numstr, '#', Num.pre + Num.post + 6);
6625  *numstr = ' ';
6626  *(numstr + Num.pre + 1) = '.';
6627  }
6628  else
6629  {
6630  numstr = psprintf("%+.*e", Num.post, value);
6631 
6632  /*
6633  * Swap a leading positive sign for a space.
6634  */
6635  if (*numstr == '+')
6636  *numstr = ' ';
6637  }
6638  }
6639  else
6640  {
6641  float8 val = value;
6642  char *orgnum;
6643  int numstr_pre_len;
6644 
6645  if (IS_MULTI(&Num))
6646  {
6647  double multi = pow((double) 10, (double) Num.multi);
6648 
6649  val = value * multi;
6650  Num.pre += Num.multi;
6651  }
6652 
6653  orgnum = psprintf("%.0f", fabs(val));
6654  numstr_pre_len = strlen(orgnum);
6655 
6656  /* adjust post digits to fit max double digits */
6657  if (numstr_pre_len >= DBL_DIG)
6658  Num.post = 0;
6659  else if (numstr_pre_len + Num.post > DBL_DIG)
6660  Num.post = DBL_DIG - numstr_pre_len;
6661  orgnum = psprintf("%.*f", Num.post, val);
6662 
6663  if (*orgnum == '-')
6664  { /* < 0 */
6665  sign = '-';
6666  numstr = orgnum + 1;
6667  }
6668  else
6669  {
6670  sign = '+';
6671  numstr = orgnum;
6672  }
6673 
6674  if ((p = strchr(numstr, '.')))
6675  numstr_pre_len = p - numstr;
6676  else
6677  numstr_pre_len = strlen(numstr);
6678 
6679  /* needs padding? */
6680  if (numstr_pre_len < Num.pre)
6681  out_pre_spaces = Num.pre - numstr_pre_len;
6682  /* overflowed prefix digit format? */
6683  else if (numstr_pre_len > Num.pre)
6684  {
6685  numstr = (char *) palloc(Num.pre + Num.post + 2);
6686  fill_str(numstr, '#', Num.pre + Num.post + 1);
6687  *(numstr + Num.pre) = '.';
6688  }
6689  }
double float8
Definition: c.h:614
#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 2424 of file formatting.c.

2426 {
2427  return from_char_parse_int_len(dest, src, node->key->len, node, escontext);
2428 }

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

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

2586 {
2587  int len;
2588 
2589  if (localized_array == NULL)
2590  *dest = seq_search_ascii(*src, array, &len);
2591  else
2592  *dest = seq_search_localized(*src, localized_array, &len, collid);
2593 
2594  if (len <= 0)
2595  {
2596  /*
2597  * In the error report, truncate the string at the next whitespace (if
2598  * any) to avoid including irrelevant data.
2599  */
2600  char *copy = pstrdup(*src);
2601  char *c;
2602 
2603  for (c = copy; *c; c++)
2604  {
2605  if (scanner_isspace(*c))
2606  {
2607  *c = '\0';
2608  break;
2609  }
2610  }
2611 
2612  ereturn(escontext, false,
2613  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2614  errmsg("invalid value \"%s\" for \"%s\"",
2615  copy, node->key->name),
2616  errdetail("The given value did not match any of "
2617  "the allowed values for this field.")));
2618  }
2619  *src += len;
2620  return true;
2621 }
static int seq_search_localized(const char *name, char **array, int *len, Oid collid)
Definition: formatting.c:2499
static int seq_search_ascii(const char *name, const char *const *array, int *len)
Definition: formatting.c:2442
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 2291 of file formatting.c.

2293 {
2294  if (*dest != 0 && *dest != value)
2295  ereturn(escontext, false,
2296  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2297  errmsg("conflicting values for \"%s\" field in formatting string",
2298  node->key->name),
2299  errdetail("This value contradicts a previous setting "
2300  "for the same field type.")));
2301  *dest = value;
2302  return true;
2303 }

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

2266 {
2267  if (mode != FROM_CHAR_DATE_NONE)
2268  {
2269  if (tmfc->mode == FROM_CHAR_DATE_NONE)
2270  tmfc->mode = mode;
2271  else if (tmfc->mode != mode)
2272  ereturn(escontext, false,
2273  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2274  errmsg("invalid combination of date conventions"),
2275  errhint("Do not mix Gregorian and ISO week date "
2276  "conventions in a formatting template.")));
2277  }
2278  return true;
2279 }
static PgChecksumMode mode
Definition: pg_checksums.c:65

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

5139 {
5140  char *result,
5141  *p = strchr(num, '.');
5142 
5143 #ifdef DEBUG_TO_FROM_CHAR
5144  elog(DEBUG_elog_output, "get_last_relevant_decnum()");
5145 #endif
5146 
5147  if (!p)
5148  return NULL;
5149 
5150  result = p;
5151 
5152  while (*(++p))
5153  {
5154  if (*p != '0')
5155  result = p;
5156  }
5157 
5158  return result;
5159 }

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

References ereport, errcode(), errmsg(), ERROR, len, numTH, numth, TH_UPPER, and generate_unaccent_rules::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 6292 of file formatting.c.

6297 {
6299  text *fmt = PG_GETARG_TEXT_PP(1);
6300  NUMDesc Num;
6301  FormatNode *format;
6302  text *result;
6303  bool shouldFree;
6304  int out_pre_spaces = 0,
6305  sign = 0;
6306  char *numstr,
6307  *orgnum;
6308 
6310 
6311  /*
6312  * On DateType depend part (int32)
6313  */
6314  if (IS_ROMAN(&Num))
6315  numstr = int_to_roman(value);
6316  else if (IS_EEEE(&Num))
6317  {
6318  /* we can do it easily because float8 won't lose any precision */
6319  float8 val = (float8) value;
6320 
6321  orgnum = (char *) psprintf("%+.*e", Num.post, val);
6322 
6323  /*
6324  * Swap a leading positive sign for a space.
6325  */
6326  if (*orgnum == '+')
6327  *orgnum = ' ';
6328 
6329  numstr = orgnum;
6330  }
6331  else
6332  {
6333  int numstr_pre_len;
6334 
6335  if (IS_MULTI(&Num))
6336  {
6338  Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
6339  Num.pre += Num.multi;
6340  }
6341  else
6342  {
6344  Int32GetDatum(value)));
6345  }
6346 
6347  if (*orgnum == '-')
6348  {
6349  sign = '-';
6350  orgnum++;
6351  }
6352  else
6353  sign = '+';
6354 
6355  numstr_pre_len = strlen(orgnum);
6356 
6357  /* post-decimal digits? Pad out with zeros. */
6358  if (Num.post)
6359  {
6360  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6361  strcpy(numstr, orgnum);
6362  *(numstr + numstr_pre_len) = '.';
6363  memset(numstr + numstr_pre_len + 1, '0', Num.post);
6364  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6365  }
6366  else
6367  numstr = orgnum;
6368 
6369  /* needs padding? */
6370  if (numstr_pre_len < Num.pre)
6371  out_pre_spaces = Num.pre - numstr_pre_len;
6372  /* overflowed prefix digit format? */
6373  else if (numstr_pre_len > Num.pre)
6374  {
6375  numstr = (char *) palloc(Num.pre + Num.post + 2);
6376  fill_str(numstr, '#', Num.pre + Num.post + 1);
6377  *(numstr + Num.pre) = '.';
6378  }
6379  }
signed int int32
Definition: c.h:478
#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 6386 of file formatting.c.

6391 {
6392  int64 value = PG_GETARG_INT64(0);
6393  text *fmt = PG_GETARG_TEXT_PP(1);
6394  NUMDesc Num;
6395  FormatNode *format;
6396  text *result;
6397  bool shouldFree;
6398  int out_pre_spaces = 0,
6399  sign = 0;
6400  char *numstr,
6401  *orgnum;
6402 
6404 
6405  /*
6406  * On DateType depend part (int32)
6407  */
6408  if (IS_ROMAN(&Num))
6409  {
6410  /* Currently don't support int8 conversion to roman... */
6412  }
6413  else if (IS_EEEE(&Num))
6414  {
6415  /* to avoid loss of precision, must go via numeric not float8 */
6417  Num.post);
6418 
6419  /*
6420  * numeric_out_sci() does not emit a sign for positive numbers. We
6421  * need to add a space in this case so that positive and negative
6422  * numbers are aligned. We don't have to worry about NaN/inf here.
6423  */
6424  if (*orgnum != '-')
6425  {
6426  numstr = (char *) palloc(strlen(orgnum) + 2);
6427  *numstr = ' ';
6428  strcpy(numstr + 1, orgnum);
6429  }
6430  else
6431  {
6432  numstr = orgnum;
6433  }
6434  }
6435  else
6436  {
6437  int numstr_pre_len;
6438 
6439  if (IS_MULTI(&Num))
6440  {
6441  double multi = pow((double) 10, (double) Num.multi);
6442 
6446  Float8GetDatum(multi))));
6447  Num.pre += Num.multi;
6448  }
6449 
6451  Int64GetDatum(value)));
6452 
6453  if (*orgnum == '-')
6454  {
6455  sign = '-';
6456  orgnum++;
6457  }
6458  else
6459  sign = '+';
6460 
6461  numstr_pre_len = strlen(orgnum);
6462 
6463  /* post-decimal digits? Pad out with zeros. */
6464  if (Num.post)
6465  {
6466  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
6467  strcpy(numstr, orgnum);
6468  *(numstr + numstr_pre_len) = '.';
6469  memset(numstr + numstr_pre_len + 1, '0', Num.post);
6470  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
6471  }
6472  else
6473  numstr = orgnum;
6474 
6475  /* needs padding? */
6476  if (numstr_pre_len < Num.pre)
6477  out_pre_spaces = Num.pre - numstr_pre_len;
6478  /* overflowed prefix digit format? */
6479  else if (numstr_pre_len > Num.pre)
6480  {
6481  numstr = (char *) palloc(Num.pre + Num.post + 2);
6482  fill_str(numstr, '#', Num.pre + Num.post + 1);
6483  *(numstr + Num.pre) = '.';
6484  }
6485  }
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:1778
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1787
#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 5007 of file formatting.c.

5008 {
5009  int len,
5010  num;
5011  char *p,
5012  *result,
5013  numstr[12];
5014 
5015  result = (char *) palloc(16);
5016  *result = '\0';
5017 
5018  if (number > 3999 || number < 1)
5019  {
5020  fill_str(result, '#', 15);
5021  return result;
5022  }
5023  len = snprintf(numstr, sizeof(numstr), "%d", number);
5024 
5025  for (p = numstr; *p != '\0'; p++, --len)
5026  {
5027  num = *p - ('0' + 1);
5028  if (num < 0)
5029  continue;
5030 
5031  if (len > 3)
5032  {
5033  while (num-- != -1)
5034  strcat(result, "M");
5035  }
5036  else
5037  {
5038  if (len == 3)
5039  strcat(result, rm100[num]);
5040  else if (len == 2)
5041  strcat(result, rm10[num]);
5042  else if (len == 1)
5043  strcat(result, rm1[num]);
5044  }
5045  }
5046  return result;
5047 }
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 4138 of file formatting.c.

4139 {
4140  Interval *it = PG_GETARG_INTERVAL_P(0);
4141  text *fmt = PG_GETARG_TEXT_PP(1),
4142  *res;
4143  TmToChar tmtc;
4144  struct fmt_tm *tm;
4145  struct pg_itm tt,
4146  *itm = &tt;
4147 
4148  if (VARSIZE_ANY_EXHDR(fmt) <= 0)
4149  PG_RETURN_NULL();
4150 
4151  ZERO_tmtc(&tmtc);
4152  tm = tmtcTm(&tmtc);
4153 
4154  interval2itm(*it, itm);
4155  tmtc.fsec = itm->tm_usec;
4156  tm->tm_sec = itm->tm_sec;
4157  tm->tm_min = itm->tm_min;
4158  tm->tm_hour = itm->tm_hour;
4159  tm->tm_mday = itm->tm_mday;
4160  tm->tm_mon = itm->tm_mon;
4161  tm->tm_year = itm->tm_year;
4162 
4163  /* wday is meaningless, yday approximates the total span in days */
4165 
4166  if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
4167  PG_RETURN_NULL();
4168 
4170 }
void interval2itm(Interval span, struct pg_itm *itm)
Definition: timestamp.c:1976
#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:3993
#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(), 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 2185 of file formatting.c.

2186 {
2187  if (n->type == NODE_TYPE_END)
2188  return false;
2189 
2190  if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
2191  return true;
2192 
2193  /*
2194  * Next node
2195  */
2196  n++;
2197 
2198  /* end of format string is treated like a non-digit separator */
2199  if (n->type ==