PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
formatting.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include "catalog/pg_collation.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/formatting.h"
#include "utils/int8.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
Include dependency graph for formatting.c:

Go to the source code of this file.

Data Structures

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

Macros

#define DCH_TYPE   1 /* DATE-TIME version */
 
#define NUM_TYPE   2 /* NUMBER version */
 
#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 MAXFLOATWIDTH   60
 
#define MAXDOUBLEWIDTH   500
 
#define NODE_TYPE_END   1
 
#define NODE_TYPE_ACTION   2
 
#define NODE_TYPE_CHAR   3
 
#define SUFFTYPE_PREFIX   1
 
#define SUFFTYPE_POSTFIX   2
 
#define CLOCK_24_HOUR   0
 
#define CLOCK_12_HOUR   1
 
#define ADJUST_YEAR(year, is_interval)   ((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
 
#define A_D_STR   "A.D."
 
#define a_d_STR   "a.d."
 
#define AD_STR   "AD"
 
#define ad_STR   "ad"
 
#define B_C_STR   "B.C."
 
#define b_c_STR   "b.c."
 
#define BC_STR   "BC"
 
#define bc_STR   "bc"
 
#define A_M_STR   "A.M."
 
#define a_m_STR   "a.m."
 
#define AM_STR   "AM"
 
#define am_STR   "am"
 
#define P_M_STR   "P.M."
 
#define p_m_STR   "p.m."
 
#define PM_STR   "PM"
 
#define pm_STR   "pm"
 
#define ONE_UPPER   1 /* Name */
 
#define ALL_UPPER   2 /* NAME */
 
#define ALL_LOWER   3 /* name */
 
#define FULL_SIZ   0
 
#define MAX_MONTH_LEN   9
 
#define MAX_MON_LEN   3
 
#define MAX_DAY_LEN   9
 
#define MAX_DY_LEN   3
 
#define MAX_RM_LEN   4
 
#define TH_UPPER   1
 
#define TH_LOWER   2
 
#define NUM_F_DECIMAL   (1 << 1)
 
#define NUM_F_LDECIMAL   (1 << 2)
 
#define NUM_F_ZERO   (1 << 3)
 
#define NUM_F_BLANK   (1 << 4)
 
#define NUM_F_FILLMODE   (1 << 5)
 
#define NUM_F_LSIGN   (1 << 6)
 
#define NUM_F_BRACKET   (1 << 7)
 
#define NUM_F_MINUS   (1 << 8)
 
#define NUM_F_PLUS   (1 << 9)
 
#define NUM_F_ROMAN   (1 << 10)
 
#define NUM_F_MULTI   (1 << 11)
 
#define NUM_F_PLUS_POST   (1 << 12)
 
#define NUM_F_MINUS_POST   (1 << 13)
 
#define NUM_F_EEEE   (1 << 14)
 
#define NUM_LSIGN_PRE   (-1)
 
#define NUM_LSIGN_POST   1
 
#define NUM_LSIGN_NONE   0
 
#define IS_DECIMAL(_f)   ((_f)->flag & NUM_F_DECIMAL)
 
#define IS_LDECIMAL(_f)   ((_f)->flag & NUM_F_LDECIMAL)
 
#define IS_ZERO(_f)   ((_f)->flag & NUM_F_ZERO)
 
#define IS_BLANK(_f)   ((_f)->flag & NUM_F_BLANK)
 
#define IS_FILLMODE(_f)   ((_f)->flag & NUM_F_FILLMODE)
 
#define IS_BRACKET(_f)   ((_f)->flag & NUM_F_BRACKET)
 
#define IS_MINUS(_f)   ((_f)->flag & NUM_F_MINUS)
 
#define IS_LSIGN(_f)   ((_f)->flag & NUM_F_LSIGN)
 
#define IS_PLUS(_f)   ((_f)->flag & NUM_F_PLUS)
 
#define IS_ROMAN(_f)   ((_f)->flag & NUM_F_ROMAN)
 
#define IS_MULTI(_f)   ((_f)->flag & NUM_F_MULTI)
 
#define IS_EEEE(_f)   ((_f)->flag & NUM_F_EEEE)
 
#define NUM_CACHE_SIZE   64
 
#define NUM_CACHE_ENTRIES   20
 
#define DCH_CACHE_SIZE   128
 
#define DCH_CACHE_ENTRIES   20
 
#define ZERO_tmfc(_X)   memset(_X, 0, sizeof(TmFromChar))
 
#define DEBUG_TMFC(_X)
 
#define DEBUG_TM(_X)
 
#define tmtcTm(_X)   (&(_X)->tm)
 
#define tmtcTzn(_X)   ((_X)->tzn)
 
#define tmtcFsec(_X)   ((_X)->fsec)
 
#define ZERO_tm(_X)
 
#define ZERO_tmtc(_X)
 
#define INVALID_FOR_INTERVAL
 
#define DCH_S_FM   0x01
 
#define DCH_S_TH   0x02
 
#define DCH_S_th   0x04
 
#define DCH_S_SP   0x08
 
#define DCH_S_TM   0x10
 
#define S_THth(_s)   ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
 
#define S_TH(_s)   (((_s) & DCH_S_TH) ? 1 : 0)
 
#define S_th(_s)   (((_s) & DCH_S_th) ? 1 : 0)
 
#define S_TH_TYPE(_s)   (((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
 
#define S_FM(_s)   (((_s) & DCH_S_FM) ? 1 : 0)
 
#define S_SP(_s)   (((_s) & DCH_S_SP) ? 1 : 0)
 
#define S_TM(_s)   (((_s) & DCH_S_TM) ? 1 : 0)
 
#define TM_SUFFIX_LEN   2
 
#define SKIP_THth(ptr, _suf)
 
#define zeroize_NUM(_n)
 
#define OVERLOAD_TEST   (Np->inout_p >= Np->inout + input_len)
 
#define AMOUNT_TEST(_s)   (input_len-(Np->inout_p-Np->inout) >= _s)
 
#define IS_PREDEC_SPACE(_n)
 
#define NUM_TOCHAR_prepare
 
#define NUM_TOCHAR_finish
 

Typedefs

typedef struct FormatNode FormatNode
 
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_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_SSSS, DCH_SS,
  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_fx, DCH_hh24, DCH_hh12,
  DCH_hh, DCH_iddd, DCH_id, DCH_iw,
  DCH_iyyy, DCH_iyy, DCH_iy, DCH_i,
  DCH_j, DCH_mi, DCH_mm, DCH_month,
  DCH_mon, DCH_ms, DCH_p_m, DCH_pm,
  DCH_q, DCH_rm, DCH_ssss, DCH_ss,
  DCH_tz, DCH_us, DCH_ww, DCH_w,
  DCH_y_yyy, DCH_yyyy, DCH_yyy, DCH_yy,
  DCH_y, _DCH_last_
}
 
enum  NUM_poz {
  NUM_COMMA, NUM_DEC, NUM_0, NUM_9,
  NUM_B, NUM_C, NUM_D, NUM_E,
  NUM_FM, NUM_G, NUM_L, NUM_MI,
  NUM_PL, NUM_PR, NUM_RN, NUM_SG,
  NUM_SP, NUM_S, NUM_TH, NUM_V,
  NUM_b, NUM_c, NUM_d, NUM_e,
  NUM_fm, NUM_g, NUM_l, NUM_mi,
  NUM_pl, NUM_pr, NUM_rn, NUM_sg,
  NUM_sp, NUM_s, NUM_th, NUM_v,
  _NUM_last_
}
 

Functions

static const KeyWordindex_seq_search (const char *str, const KeyWord *kw, const int *index)
 
static const KeySuffixsuff_search (const char *str, const KeySuffix *suf, int type)
 
static 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, int ver, NUMDesc *Num)
 
static void DCH_to_char (FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
 
static void DCH_from_char (FormatNode *node, char *in, TmFromChar *out)
 
static const char * get_th (char *num, int type)
 
static char * str_numth (char *dest, char *num, int type)
 
static int adjust_partial_year_to_2020 (int year)
 
static int strspace_len (char *str)
 
static void from_char_set_mode (TmFromChar *tmfc, const FromCharDateMode mode)
 
static void from_char_set_int (int *dest, const int value, const FormatNode *node)
 
static int from_char_parse_int_len (int *dest, char **src, const int len, FormatNode *node)
 
static int from_char_parse_int (int *dest, char **src, FormatNode *node)
 
static int seq_search (char *name, const char *const *array, int type, int max, int *len)
 
static int from_char_seq_search (int *dest, char **src, const char *const *array, int type, int max, FormatNode *node)
 
static void do_to_timestamp (text *date_txt, text *fmt, struct pg_tm *tm, fsec_t *fsec)
 
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 from_char_input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid)
 
static DCHCacheEntryDCH_cache_getnew (const char *str)
 
static DCHCacheEntryDCH_cache_search (const char *str)
 
static DCHCacheEntryDCH_cache_fetch (const char *str)
 
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 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 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 DCHCacheEntry DCHCache [DCH_CACHE_ENTRIES]
 
static int n_DCHCache = 0
 
static int DCHCounter = 0
 
static NUMCacheEntry NUMCache [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

#define A_D_STR   "A.D."

Definition at line 206 of file formatting.c.

Referenced by DCH_to_char().

#define a_d_STR   "a.d."

Definition at line 207 of file formatting.c.

Referenced by DCH_to_char().

#define A_M_STR   "A.M."

Definition at line 233 of file formatting.c.

Referenced by DCH_to_char().

#define a_m_STR   "a.m."

Definition at line 234 of file formatting.c.

Referenced by DCH_to_char().

#define AD_STR   "AD"

Definition at line 208 of file formatting.c.

Referenced by DCH_to_char().

#define ad_STR   "ad"

Definition at line 209 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 204 of file formatting.c.

Referenced by DCH_to_char().

#define ALL_LOWER   3 /* name */

Definition at line 289 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

#define ALL_UPPER   2 /* NAME */

Definition at line 288 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

#define AM_STR   "AM"

Definition at line 235 of file formatting.c.

Referenced by DCH_to_char().

#define am_STR   "am"

Definition at line 236 of file formatting.c.

Referenced by DCH_to_char().

#define AMOUNT_TEST (   _s)    (input_len-(Np->inout_p-Np->inout) >= _s)

Referenced by NUM_numpart_from_char().

#define B_C_STR   "B.C."

Definition at line 211 of file formatting.c.

Referenced by DCH_to_char().

#define b_c_STR   "b.c."

Definition at line 212 of file formatting.c.

Referenced by DCH_to_char().

#define BC_STR   "BC"

Definition at line 213 of file formatting.c.

Referenced by DCH_to_char().

#define bc_STR   "bc"

Definition at line 214 of file formatting.c.

Referenced by DCH_to_char().

#define CLOCK_12_HOUR   1

Definition at line 181 of file formatting.c.

Referenced by DCH_from_char(), and do_to_timestamp().

#define CLOCK_24_HOUR   0

Definition at line 180 of file formatting.c.

#define DCH_CACHE_ENTRIES   20

Definition at line 375 of file formatting.c.

Referenced by DCH_cache_getnew(), and DCH_cache_search().

#define DCH_CACHE_SIZE   128

Definition at line 374 of file formatting.c.

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

#define DCH_MAX_ITEM_SIZ   12 /* max localized day name */
#define DCH_S_FM   0x01

Definition at line 505 of file formatting.c.

#define DCH_S_SP   0x08

Definition at line 508 of file formatting.c.

#define DCH_S_TH   0x02

Definition at line 506 of file formatting.c.

#define DCH_S_th   0x04

Definition at line 507 of file formatting.c.

#define DCH_S_TM   0x10

Definition at line 509 of file formatting.c.

#define DCH_TYPE   1 /* DATE-TIME version */
#define DEBUG_TM (   _X)

Definition at line 452 of file formatting.c.

Referenced by do_to_timestamp().

#define DEBUG_TMFC (   _X)

Definition at line 451 of file formatting.c.

Referenced by do_to_timestamp().

#define FULL_SIZ   0

Definition at line 291 of file formatting.c.

#define INVALID_FOR_INTERVAL
Value:
do { \
if (is_interval) \
(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:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

Definition at line 488 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 349 of file formatting.c.

Referenced by NUMDesc_prepare().

#define IS_BRACKET (   _f)    ((_f)->flag & NUM_F_BRACKET)
#define IS_DECIMAL (   _f)    ((_f)->flag & NUM_F_DECIMAL)
#define IS_EEEE (   _f)    ((_f)->flag & NUM_F_EEEE)
#define IS_FILLMODE (   _f)    ((_f)->flag & NUM_F_FILLMODE)

Definition at line 350 of file formatting.c.

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

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

Definition at line 347 of file formatting.c.

Referenced by NUM_prepare_locale().

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

Definition at line 352 of file formatting.c.

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

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

Definition at line 354 of file formatting.c.

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

#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:348
#define FALSE
Definition: c.h:219

Definition at line 4447 of file formatting.c.

Referenced by NUM_numpart_to_char().

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

Definition at line 348 of file formatting.c.

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

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

Definition at line 111 of file formatting.c.

Referenced by index_seq_search().

#define KeyWord_INDEX_SIZE   ('~' - ' ')

Definition at line 110 of file formatting.c.

#define MAX_DAY_LEN   9

Definition at line 295 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_DY_LEN   3

Definition at line 296 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_MON_LEN   3

Definition at line 294 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_MONTH_LEN   9

Definition at line 293 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_RM_LEN   4

Definition at line 297 of file formatting.c.

Referenced by DCH_from_char().

#define MAXDOUBLEWIDTH   500

Definition at line 125 of file formatting.c.

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

#define MAXFLOATWIDTH   60

Definition at line 124 of file formatting.c.

Referenced by float4_to_char().

#define NODE_TYPE_ACTION   2
#define NODE_TYPE_CHAR   3

Definition at line 175 of file formatting.c.

Referenced by parse_format().

#define NODE_TYPE_END   1
#define NUM_CACHE_ENTRIES   20

Definition at line 373 of file formatting.c.

Referenced by NUM_cache_getnew(), and NUM_cache_search().

#define NUM_CACHE_SIZE   64

Definition at line 372 of file formatting.c.

Referenced by NUM_cache(), and NUM_cache_getnew().

#define NUM_F_BLANK   (1 << 4)

Definition at line 326 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_BRACKET   (1 << 7)

Definition at line 329 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_DECIMAL   (1 << 1)

Definition at line 323 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_EEEE   (1 << 14)

Definition at line 336 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_FILLMODE   (1 << 5)

Definition at line 327 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_LDECIMAL   (1 << 2)

Definition at line 324 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_LSIGN   (1 << 6)

Definition at line 328 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_MINUS   (1 << 8)

Definition at line 330 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_MINUS_POST   (1 << 13)

Definition at line 335 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_MULTI   (1 << 11)

Definition at line 333 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_PLUS   (1 << 9)

Definition at line 331 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_PLUS_POST   (1 << 12)

Definition at line 334 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_ROMAN   (1 << 10)

Definition at line 332 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_ZERO   (1 << 3)

Definition at line 325 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_LSIGN_NONE   0

Definition at line 340 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_LSIGN_POST   1

Definition at line 339 of file formatting.c.

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

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

Definition at line 118 of file formatting.c.

Referenced by numeric_to_number().

#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) \
\
/* \
* Convert null-terminated representation of result to standard text. \
* The result is usually much bigger than it needs to be, but there \
* seems little point in realloc'ing it smaller. \
*/ \
len = strlen(VARDATA(result)); \
SET_VARSIZE(result, len + VARHDRSZ); \
} while (0)
#define VARDATA(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:439
#define PG_GET_COLLATION()
Definition: fmgr.h:163
void pfree(void *pointer)
Definition: mcxt.c:949
char sign
Definition: informix.c:693
static char * NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, int from_char_input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid)
Definition: formatting.c:4645
static char format
Definition: pg_basebackup.c:81
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328

Definition at line 5072 of file formatting.c.

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

#define NUM_TOCHAR_prepare
Value:
do { \
int len = VARSIZE_ANY_EXHDR(fmt); \
if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ) \
result = (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
format = NUM_cache(len, &Num, fmt, &shouldFree); \
} while (0)
#define VARHDRSZ
Definition: c.h:439
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
Definition: formatting.c:4023
void * palloc0(Size size)
Definition: mcxt.c:877
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define NUM_MAX_ITEM_SIZ
Definition: formatting.c:118
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
Definition: c.h:433
static char format
Definition: pg_basebackup.c:81

Definition at line 5059 of file formatting.c.

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

#define NUM_TYPE   2 /* NUMBER version */

Definition at line 104 of file formatting.c.

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

#define ONE_UPPER   1 /* Name */

Definition at line 287 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

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

Referenced by NUM_numpart_from_char().

#define P_M_STR   "P.M."

Definition at line 238 of file formatting.c.

Referenced by DCH_to_char().

#define p_m_STR   "p.m."

Definition at line 239 of file formatting.c.

Referenced by DCH_to_char().

#define PM_STR   "PM"

Definition at line 240 of file formatting.c.

Referenced by DCH_to_char().

#define pm_STR   "pm"

Definition at line 241 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 521 of file formatting.c.

Referenced by DCH_to_char(), and from_char_parse_int_len().

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

Definition at line 522 of file formatting.c.

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

Definition at line 516 of file formatting.c.

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

Definition at line 517 of file formatting.c.

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

Definition at line 518 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 515 of file formatting.c.

Referenced by DCH_to_char(), and is_next_separator().

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

Definition at line 523 of file formatting.c.

Referenced by DCH_to_char().

#define SKIP_THth (   ptr,
  _suf 
)
Value:
do { \
if (S_THth(_suf)) \
{ \
if (*(ptr)) (ptr)++; \
if (*(ptr)) (ptr)++; \
} \
} while (0)
#define S_THth(_s)
Definition: formatting.c:515

Definition at line 2025 of file formatting.c.

Referenced by DCH_from_char().

#define SUFFTYPE_POSTFIX   2

Definition at line 178 of file formatting.c.

Referenced by parse_format().

#define SUFFTYPE_PREFIX   1

Definition at line 177 of file formatting.c.

Referenced by parse_format().

#define TH_LOWER   2

Definition at line 300 of file formatting.c.

Referenced by NUM_processor().

#define TH_UPPER   1

Definition at line 299 of file formatting.c.

Referenced by get_th(), and NUM_processor().

#define TM_SUFFIX_LEN   2

Definition at line 529 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 468 of file formatting.c.

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

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

Definition at line 466 of file formatting.c.

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

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

Definition at line 467 of file formatting.c.

Referenced by DCH_to_char(), and timestamptz_to_char().

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

Definition at line 470 of file formatting.c.

Referenced by do_to_timestamp().

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

Definition at line 432 of file formatting.c.

Referenced by do_to_timestamp().

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

Definition at line 477 of file formatting.c.

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

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

Referenced by NUM_cache(), and NUM_cache_fetch().

Typedef Documentation

Definition at line 154 of file formatting.c.

Enumeration Type Documentation

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_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_SSSS 
DCH_SS 
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_fx 
DCH_hh24 
DCH_hh12 
DCH_hh 
DCH_iddd 
DCH_id 
DCH_iw 
DCH_iyyy 
DCH_iyy 
DCH_iy 
DCH_i 
DCH_j 
DCH_mi 
DCH_mm 
DCH_month 
DCH_mon 
DCH_ms 
DCH_p_m 
DCH_pm 
DCH_q 
DCH_rm 
DCH_ssss 
DCH_ss 
DCH_tz 
DCH_us 
DCH_ww 
DCH_w 
DCH_y_yyy 
DCH_yyyy 
DCH_yyy 
DCH_yy 
DCH_y 
_DCH_last_ 

Definition at line 572 of file formatting.c.

573 {
574  DCH_A_D,
575  DCH_A_M,
576  DCH_AD,
577  DCH_AM,
578  DCH_B_C,
579  DCH_BC,
580  DCH_CC,
581  DCH_DAY,
582  DCH_DDD,
583  DCH_DD,
584  DCH_DY,
585  DCH_Day,
586  DCH_Dy,
587  DCH_D,
588  DCH_FX, /* global suffix */
589  DCH_HH24,
590  DCH_HH12,
591  DCH_HH,
592  DCH_IDDD,
593  DCH_ID,
594  DCH_IW,
595  DCH_IYYY,
596  DCH_IYY,
597  DCH_IY,
598  DCH_I,
599  DCH_J,
600  DCH_MI,
601  DCH_MM,
602  DCH_MONTH,
603  DCH_MON,
604  DCH_MS,
605  DCH_Month,
606  DCH_Mon,
607  DCH_OF,
608  DCH_P_M,
609  DCH_PM,
610  DCH_Q,
611  DCH_RM,
612  DCH_SSSS,
613  DCH_SS,
614  DCH_TZ,
615  DCH_US,
616  DCH_WW,
617  DCH_W,
618  DCH_Y_YYY,
619  DCH_YYYY,
620  DCH_YYY,
621  DCH_YY,
622  DCH_Y,
623  DCH_a_d,
624  DCH_a_m,
625  DCH_ad,
626  DCH_am,
627  DCH_b_c,
628  DCH_bc,
629  DCH_cc,
630  DCH_day,
631  DCH_ddd,
632  DCH_dd,
633  DCH_dy,
634  DCH_d,
635  DCH_fx,
636  DCH_hh24,
637  DCH_hh12,
638  DCH_hh,
639  DCH_iddd,
640  DCH_id,
641  DCH_iw,
642  DCH_iyyy,
643  DCH_iyy,
644  DCH_iy,
645  DCH_i,
646  DCH_j,
647  DCH_mi,
648  DCH_mm,
649  DCH_month,
650  DCH_mon,
651  DCH_ms,
652  DCH_p_m,
653  DCH_pm,
654  DCH_q,
655  DCH_rm,
656  DCH_ssss,
657  DCH_ss,
658  DCH_tz,
659  DCH_us,
660  DCH_ww,
661  DCH_w,
662  DCH_y_yyy,
663  DCH_yyyy,
664  DCH_yyy,
665  DCH_yy,
666  DCH_y,
667 
668  /* last */
669  _DCH_last_
670 } DCH_poz;
DCH_poz
Definition: formatting.c:572
Enumerator
FROM_CHAR_DATE_NONE 
FROM_CHAR_DATE_GREGORIAN 
FROM_CHAR_DATE_ISOWEEK 

Definition at line 147 of file formatting.c.

148 {
149  FROM_CHAR_DATE_NONE = 0, /* Value does not affect date mode. */
150  FROM_CHAR_DATE_GREGORIAN, /* Gregorian (day, month, year) style date */
151  FROM_CHAR_DATE_ISOWEEK /* ISO 8601 week date */
FromCharDateMode
Definition: formatting.c:147
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 672 of file formatting.c.

673 {
674  NUM_COMMA,
675  NUM_DEC,
676  NUM_0,
677  NUM_9,
678  NUM_B,
679  NUM_C,
680  NUM_D,
681  NUM_E,
682  NUM_FM,
683  NUM_G,
684  NUM_L,
685  NUM_MI,
686  NUM_PL,
687  NUM_PR,
688  NUM_RN,
689  NUM_SG,
690  NUM_SP,
691  NUM_S,
692  NUM_TH,
693  NUM_V,
694  NUM_b,
695  NUM_c,
696  NUM_d,
697  NUM_e,
698  NUM_fm,
699  NUM_g,
700  NUM_l,
701  NUM_mi,
702  NUM_pl,
703  NUM_pr,
704  NUM_rn,
705  NUM_sg,
706  NUM_sp,
707  NUM_s,
708  NUM_th,
709  NUM_v,
710 
711  /* last */
712  _NUM_last_
713 } NUM_poz;
NUM_poz
Definition: formatting.c:672

Function Documentation

static int adjust_partial_year_to_2020 ( int  year)
static

Definition at line 2105 of file formatting.c.

Referenced by DCH_from_char().

2106 {
2107  /*
2108  * Adjust all dates toward 2020; this is effectively what happens when we
2109  * assume '70' is 1970 and '69' is 2069.
2110  */
2111  /* Force 0-69 into the 2000's */
2112  if (year < 70)
2113  return year + 2000;
2114  /* Force 70-99 into the 1900's */
2115  else if (year < 100)
2116  return year + 1900;
2117  /* Force 100-519 into the 2000's */
2118  else if (year < 520)
2119  return year + 2000;
2120  /* Force 520-999 into the 1000's */
2121  else if (year < 1000)
2122  return year + 1000;
2123  else
2124  return year;
2125 }
char* asc_initcap ( const char *  buff,
size_t  nbytes 
)

Definition at line 1956 of file formatting.c.

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

Referenced by str_initcap().

1957 {
1958  char *result;
1959  char *p;
1960  int wasalnum = false;
1961 
1962  if (!buff)
1963  return NULL;
1964 
1965  result = pnstrdup(buff, nbytes);
1966 
1967  for (p = result; *p; p++)
1968  {
1969  char c;
1970 
1971  if (wasalnum)
1972  *p = c = pg_ascii_tolower((unsigned char) *p);
1973  else
1974  *p = c = pg_ascii_toupper((unsigned char) *p);
1975  /* we don't trust isalnum() here */
1976  wasalnum = ((c >= 'A' && c <= 'Z') ||
1977  (c >= 'a' && c <= 'z') ||
1978  (c >= '0' && c <= '9'));
1979  }
1980 
1981  return result;
1982 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1087
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
char* asc_tolower ( const char *  buff,
size_t  nbytes 
)

Definition at line 1910 of file formatting.c.

References pg_ascii_tolower(), and pnstrdup().

Referenced by asc_tolower_z(), and str_tolower().

1911 {
1912  char *result;
1913  char *p;
1914 
1915  if (!buff)
1916  return NULL;
1917 
1918  result = pnstrdup(buff, nbytes);
1919 
1920  for (p = result; *p; p++)
1921  *p = pg_ascii_tolower((unsigned char) *p);
1922 
1923  return result;
1924 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1087
unsigned char pg_ascii_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:146
static char* asc_tolower_z ( const char *  buff)
static

Definition at line 2005 of file formatting.c.

References asc_tolower().

Referenced by DCH_to_char(), and NUM_processor().

2006 {
2007  return asc_tolower(buff, strlen(buff));
2008 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:1910
char* asc_toupper ( const char *  buff,
size_t  nbytes 
)

Definition at line 1933 of file formatting.c.

References pg_ascii_toupper(), and pnstrdup().

Referenced by asc_toupper_z(), and str_toupper().

1934 {
1935  char *result;
1936  char *p;
1937 
1938  if (!buff)
1939  return NULL;
1940 
1941  result = pnstrdup(buff, nbytes);
1942 
1943  for (p = result; *p; p++)
1944  *p = pg_ascii_toupper((unsigned char) *p);
1945 
1946  return result;
1947 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1087
unsigned char pg_ascii_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:135
static char* asc_toupper_z ( const char *  buff)
static

Definition at line 2011 of file formatting.c.

References asc_toupper().

Referenced by DCH_to_char().

2012 {
2013  return asc_toupper(buff, strlen(buff));
2014 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:1933
static text* datetime_to_char_body ( TmToChar tmtc,
text fmt,
bool  is_interval,
Oid  collid 
)
static

Definition at line 3367 of file formatting.c.

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

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

3368 {
3369  FormatNode *format;
3370  char *fmt_str,
3371  *result;
3372  bool incache;
3373  int fmt_len;
3374  text *res;
3375 
3376  /*
3377  * Convert fmt to C string
3378  */
3379  fmt_str = text_to_cstring(fmt);
3380  fmt_len = strlen(fmt_str);
3381 
3382  /*
3383  * Allocate workspace for result as C string
3384  */
3385  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
3386  *result = '\0';
3387 
3388  if (fmt_len > DCH_CACHE_SIZE)
3389  {
3390  /*
3391  * Allocate new memory if format picture is bigger than static cache
3392  * and do not use cache (call parser always)
3393  */
3394  incache = FALSE;
3395 
3396  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3397 
3398  parse_format(format, fmt_str, DCH_keywords,
3399  DCH_suff, DCH_index, DCH_TYPE, NULL);
3400  }
3401  else
3402  {
3403  /*
3404  * Use cache buffers
3405  */
3406  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3407 
3408  incache = TRUE;
3409  format = ent->format;
3410  }
3411 
3412  /* The real work is here */
3413  DCH_to_char(format, is_interval, tmtc, result, collid);
3414 
3415  if (!incache)
3416  pfree(format);
3417 
3418  pfree(fmt_str);
3419 
3420  /* convert C-string result to TEXT format */
3421  res = cstring_to_text(result);
3422 
3423  pfree(result);
3424  return res;
3425 }
struct FormatNode FormatNode
Definition: formatting.c:154
static const KeySuffix DCH_suff[]
Definition: formatting.c:531
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:873
void pfree(void *pointer)
Definition: mcxt.c:949
#define DCH_CACHE_SIZE
Definition: formatting.c:374
#define FALSE
Definition: c.h:219
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
Definition: formatting.c:1227
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
Definition: formatting.c:2411
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:379
static DCHCacheEntry * DCH_cache_fetch(const char *str)
Definition: formatting.c:3340
#define DCH_TYPE
Definition: formatting.c:103
text * cstring_to_text(const char *s)
Definition: varlena.c:149
char * text_to_cstring(const text *t)
Definition: varlena.c:182
void * palloc(Size size)
Definition: mcxt.c:848
static const KeyWord DCH_keywords[]
Definition: formatting.c:719
Definition: c.h:433
#define TRUE
Definition: c.h:215
static char format
Definition: pg_basebackup.c:81
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:117
static DCHCacheEntry * DCH_cache_fetch ( const char *  str)
static

Definition at line 3340 of file formatting.c.

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

Referenced by datetime_to_char_body(), and do_to_timestamp().

3341 {
3342  DCHCacheEntry *ent;
3343 
3344  if ((ent = DCH_cache_search(str)) == NULL)
3345  {
3346  /*
3347  * Not in the cache, must run parser and save a new format-picture to
3348  * the cache. Do not mark the cache entry valid until parsing
3349  * succeeds.
3350  */
3351  ent = DCH_cache_getnew(str);
3352 
3353  parse_format(ent->format, str, DCH_keywords,
3354  DCH_suff, DCH_index, DCH_TYPE, NULL);
3355 
3356  ent->valid = true;
3357  }
3358  return ent;
3359 }
static DCHCacheEntry * DCH_cache_getnew(const char *str)
Definition: formatting.c:3250
static const KeySuffix DCH_suff[]
Definition: formatting.c:531
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:873
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
Definition: formatting.c:1227
static DCHCacheEntry * DCH_cache_search(const char *str)
Definition: formatting.c:3312
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:379
#define DCH_TYPE
Definition: formatting.c:103
static const KeyWord DCH_keywords[]
Definition: formatting.c:719
static DCHCacheEntry * DCH_cache_getnew ( const char *  str)
static

Definition at line 3250 of file formatting.c.

References DCHCacheEntry::age, DCH_CACHE_ENTRIES, DCH_CACHE_SIZE, DCHCounter, elog, n_DCHCache, DCHCacheEntry::str, StrNCpy, and DCHCacheEntry::valid.

Referenced by DCH_cache_fetch().

3251 {
3252  DCHCacheEntry *ent;
3253 
3254  /* counter overflow check - paranoia? */
3255  if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3256  {
3257  DCHCounter = 0;
3258 
3259  for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3260  ent->age = (++DCHCounter);
3261  }
3262 
3263  /*
3264  * If cache is full, remove oldest entry (or recycle first not-valid one)
3265  */
3267  {
3268  DCHCacheEntry *old = DCHCache + 0;
3269 
3270 #ifdef DEBUG_TO_FROM_CHAR
3271  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3272 #endif
3273  if (old->valid)
3274  {
3275  for (ent = DCHCache + 1; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3276  {
3277  if (!ent->valid)
3278  {
3279  old = ent;
3280  break;
3281  }
3282  if (ent->age < old->age)
3283  old = ent;
3284  }
3285  }
3286 #ifdef DEBUG_TO_FROM_CHAR
3287  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3288 #endif
3289  old->valid = false;
3290  StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
3291  old->age = (++DCHCounter);
3292  /* caller is expected to fill format, then set valid */
3293  return old;
3294  }
3295  else
3296  {
3297 #ifdef DEBUG_TO_FROM_CHAR
3298  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3299 #endif
3300  ent = DCHCache + n_DCHCache;
3301  ent->valid = false;
3302  StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
3303  ent->age = (++DCHCounter);
3304  /* caller is expected to fill format, then set valid */
3305  ++n_DCHCache;
3306  return ent;
3307  }
3308 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:380
#define DCH_CACHE_SIZE
Definition: formatting.c:374
static int n_DCHCache
Definition: formatting.c:396
#define DCH_CACHE_ENTRIES
Definition: formatting.c:375
static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:395
#define StrNCpy(dst, src, len)
Definition: c.h:836
#define elog
Definition: elog.h:219
static int DCHCounter
Definition: formatting.c:397
static DCHCacheEntry * DCH_cache_search ( const char *  str)
static

Definition at line 3312 of file formatting.c.

References DCHCacheEntry::age, DCH_CACHE_ENTRIES, DCHCounter, i, n_DCHCache, DCHCacheEntry::str, and DCHCacheEntry::valid.

Referenced by DCH_cache_fetch().

3313 {
3314  int i;
3315  DCHCacheEntry *ent;
3316 
3317  /* counter overflow check - paranoia? */
3318  if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3319  {
3320  DCHCounter = 0;
3321 
3322  for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3323  ent->age = (++DCHCounter);
3324  }
3325 
3326  for (i = 0, ent = DCHCache; i < n_DCHCache; i++, ent++)
3327  {
3328  if (ent->valid && strcmp(ent->str, str) == 0)
3329  {
3330  ent->age = (++DCHCounter);
3331  return ent;
3332  }
3333  }
3334 
3335  return NULL;
3336 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:380
static int n_DCHCache
Definition: formatting.c:396
#define DCH_CACHE_ENTRIES
Definition: formatting.c:375
static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:395
int i
static int DCHCounter
Definition: formatting.c:397
static void DCH_from_char ( FormatNode node,
char *  in,
TmFromChar out 
)
static

Definition at line 2978 of file formatting.c.

References adbc_strings, adbc_strings_long, adjust_partial_year_to_2020(), ALL_LOWER, ALL_UPPER, ampm_strings, ampm_strings_long, TmFromChar::bc, TmFromChar::cc, TmFromChar::clock, CLOCK_12_HOUR, TmFromChar::d, KeyWord::date_mode, days, DCH_A_D, DCH_a_d, DCH_A_M, DCH_a_m, DCH_AD, DCH_ad, DCH_AM, DCH_am, DCH_B_C, DCH_b_c, DCH_BC, DCH_bc, DCH_CC, DCH_D, DCH_DAY, DCH_Day, DCH_day, DCH_DD, DCH_DDD, DCH_DY, DCH_Dy, DCH_dy, DCH_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_US, DCH_W, DCH_WW, DCH_Y, DCH_Y_YYY, DCH_YY, DCH_YYY, DCH_YYYY, TmFromChar::dd, TmFromChar::ddd, ereport, errcode(), errmsg(), ERROR, 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, TmFromChar::j, FormatNode::key, KeyWord::len, MAX_DAY_LEN, MAX_DY_LEN, MAX_MON_LEN, MAX_MONTH_LEN, MAX_RM_LEN, TmFromChar::mi, TmFromChar::mm, months, months_full, MONTHS_PER_YEAR, TmFromChar::ms, KeyWord::name, NODE_TYPE_ACTION, NODE_TYPE_END, ONE_UPPER, TmFromChar::pm, rm_months_lower, rm_months_upper, SKIP_THth, TmFromChar::ss, TmFromChar::ssss, FormatNode::suffix, FormatNode::type, TmFromChar::us, value, TmFromChar::w, TmFromChar::ww, TmFromChar::year, and TmFromChar::yysz.

Referenced by do_to_timestamp().

2979 {
2980  FormatNode *n;
2981  char *s;
2982  int len,
2983  value;
2984  bool fx_mode = false;
2985 
2986  for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
2987  {
2988  if (n->type != NODE_TYPE_ACTION)
2989  {
2990  /*
2991  * Separator, so consume one character from input string. Notice
2992  * we don't insist that the consumed character match the format's
2993  * character.
2994  */
2995  s++;
2996  continue;
2997  }
2998 
2999  /* Ignore spaces before fields when not in FX (fixed width) mode */
3000  if (!fx_mode && n->key->id != DCH_FX)
3001  {
3002  while (*s != '\0' && isspace((unsigned char) *s))
3003  s++;
3004  }
3005 
3006  from_char_set_mode(out, n->key->date_mode);
3007 
3008  switch (n->key->id)
3009  {
3010  case DCH_FX:
3011  fx_mode = true;
3012  break;
3013  case DCH_A_M:
3014  case DCH_P_M:
3015  case DCH_a_m:
3016  case DCH_p_m:
3018  ALL_UPPER, n->key->len, n);
3019  from_char_set_int(&out->pm, value % 2, n);
3020  out->clock = CLOCK_12_HOUR;
3021  break;
3022  case DCH_AM:
3023  case DCH_PM:
3024  case DCH_am:
3025  case DCH_pm:
3026  from_char_seq_search(&value, &s, ampm_strings,
3027  ALL_UPPER, n->key->len, n);
3028  from_char_set_int(&out->pm, value % 2, n);
3029  out->clock = CLOCK_12_HOUR;
3030  break;
3031  case DCH_HH:
3032  case DCH_HH12:
3033  from_char_parse_int_len(&out->hh, &s, 2, n);
3034  out->clock = CLOCK_12_HOUR;
3035  SKIP_THth(s, n->suffix);
3036  break;
3037  case DCH_HH24:
3038  from_char_parse_int_len(&out->hh, &s, 2, n);
3039  SKIP_THth(s, n->suffix);
3040  break;
3041  case DCH_MI:
3042  from_char_parse_int(&out->mi, &s, n);
3043  SKIP_THth(s, n->suffix);
3044  break;
3045  case DCH_SS:
3046  from_char_parse_int(&out->ss, &s, n);
3047  SKIP_THth(s, n->suffix);
3048  break;
3049  case DCH_MS: /* millisecond */
3050  len = from_char_parse_int_len(&out->ms, &s, 3, n);
3051 
3052  /*
3053  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
3054  */
3055  out->ms *= len == 1 ? 100 :
3056  len == 2 ? 10 : 1;
3057 
3058  SKIP_THth(s, n->suffix);
3059  break;
3060  case DCH_US: /* microsecond */
3061  len = from_char_parse_int_len(&out->us, &s, 6, n);
3062 
3063  out->us *= len == 1 ? 100000 :
3064  len == 2 ? 10000 :
3065  len == 3 ? 1000 :
3066  len == 4 ? 100 :
3067  len == 5 ? 10 : 1;
3068 
3069  SKIP_THth(s, n->suffix);
3070  break;
3071  case DCH_SSSS:
3072  from_char_parse_int(&out->ssss, &s, n);
3073  SKIP_THth(s, n->suffix);
3074  break;
3075  case DCH_tz:
3076  case DCH_TZ:
3077  case DCH_OF:
3078  ereport(ERROR,
3079  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3080  errmsg("formatting field \"%s\" is only supported in to_char",
3081  n->key->name)));
3082  break;
3083  case DCH_A_D:
3084  case DCH_B_C:
3085  case DCH_a_d:
3086  case DCH_b_c:
3088  ALL_UPPER, n->key->len, n);
3089  from_char_set_int(&out->bc, value % 2, n);
3090  break;
3091  case DCH_AD:
3092  case DCH_BC:
3093  case DCH_ad:
3094  case DCH_bc:
3095  from_char_seq_search(&value, &s, adbc_strings,
3096  ALL_UPPER, n->key->len, n);
3097  from_char_set_int(&out->bc, value % 2, n);
3098  break;
3099  case DCH_MONTH:
3100  case DCH_Month:
3101  case DCH_month:
3103  MAX_MONTH_LEN, n);
3104  from_char_set_int(&out->mm, value + 1, n);
3105  break;
3106  case DCH_MON:
3107  case DCH_Mon:
3108  case DCH_mon:
3109  from_char_seq_search(&value, &s, months, ONE_UPPER,
3110  MAX_MON_LEN, n);
3111  from_char_set_int(&out->mm, value + 1, n);
3112  break;
3113  case DCH_MM:
3114  from_char_parse_int(&out->mm, &s, n);
3115  SKIP_THth(s, n->suffix);
3116  break;
3117  case DCH_DAY:
3118  case DCH_Day:
3119  case DCH_day:
3120  from_char_seq_search(&value, &s, days, ONE_UPPER,
3121  MAX_DAY_LEN, n);
3122  from_char_set_int(&out->d, value, n);
3123  out->d++;
3124  break;
3125  case DCH_DY:
3126  case DCH_Dy:
3127  case DCH_dy:
3128  from_char_seq_search(&value, &s, days, ONE_UPPER,
3129  MAX_DY_LEN, n);
3130  from_char_set_int(&out->d, value, n);
3131  out->d++;
3132  break;
3133  case DCH_DDD:
3134  from_char_parse_int(&out->ddd, &s, n);
3135  SKIP_THth(s, n->suffix);
3136  break;
3137  case DCH_IDDD:
3138  from_char_parse_int_len(&out->ddd, &s, 3, n);
3139  SKIP_THth(s, n->suffix);
3140  break;
3141  case DCH_DD:
3142  from_char_parse_int(&out->dd, &s, n);
3143  SKIP_THth(s, n->suffix);
3144  break;
3145  case DCH_D:
3146  from_char_parse_int(&out->d, &s, n);
3147  SKIP_THth(s, n->suffix);
3148  break;
3149  case DCH_ID:
3150  from_char_parse_int_len(&out->d, &s, 1, n);
3151  /* Shift numbering to match Gregorian where Sunday = 1 */
3152  if (++out->d > 7)
3153  out->d = 1;
3154  SKIP_THth(s, n->suffix);
3155  break;
3156  case DCH_WW:
3157  case DCH_IW:
3158  from_char_parse_int(&out->ww, &s, n);
3159  SKIP_THth(s, n->suffix);
3160  break;
3161  case DCH_Q:
3162 
3163  /*
3164  * We ignore 'Q' when converting to date because it is unclear
3165  * which date in the quarter to use, and some people specify
3166  * both quarter and month, so if it was honored it might
3167  * conflict with the supplied month. That is also why we don't
3168  * throw an error.
3169  *
3170  * We still parse the source string for an integer, but it
3171  * isn't stored anywhere in 'out'.
3172  */
3173  from_char_parse_int((int *) NULL, &s, n);
3174  SKIP_THth(s, n->suffix);
3175  break;
3176  case DCH_CC:
3177  from_char_parse_int(&out->cc, &s, n);
3178  SKIP_THth(s, n->suffix);
3179  break;
3180  case DCH_Y_YYY:
3181  {
3182  int matched,
3183  years,
3184  millennia,
3185  nch;
3186 
3187  matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3188  if (matched < 2)
3189  ereport(ERROR,
3190  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3191  errmsg("invalid input string for \"Y,YYY\"")));
3192  years += (millennia * 1000);
3193  from_char_set_int(&out->year, years, n);
3194  out->yysz = 4;
3195  s += nch;
3196  SKIP_THth(s, n->suffix);
3197  }
3198  break;
3199  case DCH_YYYY:
3200  case DCH_IYYY:
3201  from_char_parse_int(&out->year, &s, n);
3202  out->yysz = 4;
3203  SKIP_THth(s, n->suffix);
3204  break;
3205  case DCH_YYY:
3206  case DCH_IYY:
3207  if (from_char_parse_int(&out->year, &s, n) < 4)
3208  out->year = adjust_partial_year_to_2020(out->year);
3209  out->yysz = 3;
3210  SKIP_THth(s, n->suffix);
3211  break;
3212  case DCH_YY:
3213  case DCH_IY:
3214  if (from_char_parse_int(&out->year, &s, n) < 4)
3215  out->year = adjust_partial_year_to_2020(out->year);
3216  out->yysz = 2;
3217  SKIP_THth(s, n->suffix);
3218  break;
3219  case DCH_Y:
3220  case DCH_I:
3221  if (from_char_parse_int(&out->year, &s, n) < 4)
3222  out->year = adjust_partial_year_to_2020(out->year);
3223  out->yysz = 1;
3224  SKIP_THth(s, n->suffix);
3225  break;
3226  case DCH_RM:
3228  ALL_UPPER, MAX_RM_LEN, n);
3229  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
3230  break;
3231  case DCH_rm:
3233  ALL_LOWER, MAX_RM_LEN, n);
3234  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
3235  break;
3236  case DCH_W:
3237  from_char_parse_int(&out->w, &s, n);
3238  SKIP_THth(s, n->suffix);
3239  break;
3240  case DCH_J:
3241  from_char_parse_int(&out->j, &s, n);
3242  SKIP_THth(s, n->suffix);
3243  break;
3244  }
3245  }
3246 }
#define NODE_TYPE_END
Definition: formatting.c:173
const KeyWord * key
Definition: formatting.c:168
static const char *const adbc_strings_long[]
Definition: formatting.c:227
static void from_char_set_int(int *dest, const int value, const FormatNode *node)
Definition: formatting.c:2170
FromCharDateMode date_mode
Definition: formatting.c:162
#define MAX_DY_LEN
Definition: formatting.c:296
int errcode(int sqlerrcode)
Definition: elog.c:575
static const char *const rm_months_upper[]
Definition: formatting.c:262
int id
Definition: formatting.c:160
static const char *const ampm_strings_long[]
Definition: formatting.c:254
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node)
Definition: formatting.c:2203
static const char *const adbc_strings[]
Definition: formatting.c:226
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define MAX_MON_LEN
Definition: formatting.c:294
#define ONE_UPPER
Definition: formatting.c:287
const char *const months[]
Definition: datetime.c:66
#define NODE_TYPE_ACTION
Definition: formatting.c:174
#define ERROR
Definition: elog.h:43
static int from_char_seq_search(int *dest, char **src, const char *const *array, int type, int max, FormatNode *node)
Definition: formatting.c:2381
static struct @121 value
#define SKIP_THth(ptr, _suf)
Definition: formatting.c:2025
const char *const days[]
Definition: datetime.c:69
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAX_RM_LEN
Definition: formatting.c:297
#define CLOCK_12_HOUR
Definition: formatting.c:181
static const char *const ampm_strings[]
Definition: formatting.c:253
const char * name
Definition: formatting.c:158
static const char *const months_full[]
Definition: formatting.c:188
int len
Definition: formatting.c:159
#define ALL_UPPER
Definition: formatting.c:288
static int adjust_partial_year_to_2020(int year)
Definition: formatting.c:2105
#define MAX_MONTH_LEN
Definition: formatting.c:293
static int from_char_parse_int(int *dest, char **src, FormatNode *node)
Definition: formatting.c:2293
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode)
Definition: formatting.c:2148
#define ALL_LOWER
Definition: formatting.c:289
#define MAX_DAY_LEN
Definition: formatting.c:295
static const char *const rm_months_lower[]
Definition: formatting.c:265
static void DCH_to_char ( FormatNode node,
bool  is_interval,
TmToChar in,
char *  out,
Oid  collid 
)
static

Definition at line 2411 of file formatting.c.

References A_D_STR, a_d_STR, A_M_STR, a_m_STR, AD_STR, ad_STR, ADJUST_YEAR, AM_STR, am_STR, asc_tolower_z(), asc_toupper_z(), B_C_STR, b_c_STR, BC_STR, bc_STR, cache_locale_time(), FormatNode::character, date2isoweek(), date2isoyear(), date2isoyearday(), date2j(), days, days_short, DCH_A_D, DCH_a_d, DCH_A_M, DCH_a_m, DCH_AD, DCH_ad, DCH_AM, DCH_am, DCH_B_C, DCH_b_c, DCH_BC, DCH_bc, DCH_CC, DCH_D, DCH_DAY, DCH_Day, DCH_day, DCH_DD, DCH_DDD, DCH_DY, DCH_Dy, DCH_dy, DCH_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_TZ, DCH_tz, 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, str_initcap_z(), str_numth(), str_tolower_z(), str_toupper_z(), FormatNode::suffix, tm, TmToChar::tm, pg_tm::tm_gmtoff, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, TM_SUFFIX_LEN, pg_tm::tm_wday, pg_tm::tm_yday, pg_tm::tm_year, tmtcTzn, and FormatNode::type.

Referenced by datetime_to_char_body().

2412 {
2413  FormatNode *n;
2414  char *s;
2415  struct pg_tm *tm = &in->tm;
2416  int i;
2417 
2418  /* cache localized days and months */
2420 
2421  s = out;
2422  for (n = node; n->type != NODE_TYPE_END; n++)
2423  {
2424  if (n->type != NODE_TYPE_ACTION)
2425  {
2426  *s = n->character;
2427  s++;
2428  continue;
2429  }
2430 
2431  switch (n->key->id)
2432  {
2433  case DCH_A_M:
2434  case DCH_P_M:
2435  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2436  ? P_M_STR : A_M_STR);
2437  s += strlen(s);
2438  break;
2439  case DCH_AM:
2440  case DCH_PM:
2441  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2442  ? PM_STR : AM_STR);
2443  s += strlen(s);
2444  break;
2445  case DCH_a_m:
2446  case DCH_p_m:
2447  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2448  ? p_m_STR : a_m_STR);
2449  s += strlen(s);
2450  break;
2451  case DCH_am:
2452  case DCH_pm:
2453  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2454  ? pm_STR : am_STR);
2455  s += strlen(s);
2456  break;
2457  case DCH_HH:
2458  case DCH_HH12:
2459 
2460  /*
2461  * display time as shown on a 12-hour clock, even for
2462  * intervals
2463  */
2464  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2465  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? HOURS_PER_DAY / 2 :
2466  tm->tm_hour % (HOURS_PER_DAY / 2));
2467  if (S_THth(n->suffix))
2468  str_numth(s, s, S_TH_TYPE(n->suffix));
2469  s += strlen(s);
2470  break;
2471  case DCH_HH24:
2472  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2473  tm->tm_hour);
2474  if (S_THth(n->suffix))
2475  str_numth(s, s, S_TH_TYPE(n->suffix));
2476  s += strlen(s);
2477  break;
2478  case DCH_MI:
2479  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2480  tm->tm_min);
2481  if (S_THth(n->suffix))
2482  str_numth(s, s, S_TH_TYPE(n->suffix));
2483  s += strlen(s);
2484  break;
2485  case DCH_SS:
2486  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2487  tm->tm_sec);
2488  if (S_THth(n->suffix))
2489  str_numth(s, s, S_TH_TYPE(n->suffix));
2490  s += strlen(s);
2491  break;
2492  case DCH_MS: /* millisecond */
2493  sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
2494  if (S_THth(n->suffix))
2495  str_numth(s, s, S_TH_TYPE(n->suffix));
2496  s += strlen(s);
2497  break;
2498  case DCH_US: /* microsecond */
2499  sprintf(s, "%06d", (int) in->fsec);
2500  if (S_THth(n->suffix))
2501  str_numth(s, s, S_TH_TYPE(n->suffix));
2502  s += strlen(s);
2503  break;
2504  case DCH_SSSS:
2505  sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2506  tm->tm_min * SECS_PER_MINUTE +
2507  tm->tm_sec);
2508  if (S_THth(n->suffix))
2509  str_numth(s, s, S_TH_TYPE(n->suffix));
2510  s += strlen(s);
2511  break;
2512  case DCH_tz:
2514  if (tmtcTzn(in))
2515  {
2516  /* We assume here that timezone names aren't localized */
2517  char *p = asc_tolower_z(tmtcTzn(in));
2518 
2519  strcpy(s, p);
2520  pfree(p);
2521  s += strlen(s);
2522  }
2523  break;
2524  case DCH_TZ:
2526  if (tmtcTzn(in))
2527  {
2528  strcpy(s, tmtcTzn(in));
2529  s += strlen(s);
2530  }
2531  break;
2532  case DCH_OF:
2534  sprintf(s, "%c%0*d",
2535  (tm->tm_gmtoff >= 0) ? '+' : '-',
2536  S_FM(n->suffix) ? 0 : 2,
2537  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2538  s += strlen(s);
2539  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2540  {
2541  sprintf(s, ":%02d",
2542  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2543  s += strlen(s);
2544  }
2545  break;
2546  case DCH_A_D:
2547  case DCH_B_C:
2549  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2550  s += strlen(s);
2551  break;
2552  case DCH_AD:
2553  case DCH_BC:
2555  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2556  s += strlen(s);
2557  break;
2558  case DCH_a_d:
2559  case DCH_b_c:
2561  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2562  s += strlen(s);
2563  break;
2564  case DCH_ad:
2565  case DCH_bc:
2567  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2568  s += strlen(s);
2569  break;
2570  case DCH_MONTH:
2572  if (!tm->tm_mon)
2573  break;
2574  if (S_TM(n->suffix))
2575  {
2576  char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2577 
2578  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2579  strcpy(s, str);
2580  else
2581  ereport(ERROR,
2582  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2583  errmsg("localized string format value too long")));
2584  }
2585  else
2586  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2587  asc_toupper_z(months_full[tm->tm_mon - 1]));
2588  s += strlen(s);
2589  break;
2590  case DCH_Month:
2592  if (!tm->tm_mon)
2593  break;
2594  if (S_TM(n->suffix))
2595  {
2596  char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2597 
2598  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2599  strcpy(s, str);
2600  else
2601  ereport(ERROR,
2602  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2603  errmsg("localized string format value too long")));
2604  }
2605  else
2606  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2607  months_full[tm->tm_mon - 1]);
2608  s += strlen(s);
2609  break;
2610  case DCH_month:
2612  if (!tm->tm_mon)
2613  break;
2614  if (S_TM(n->suffix))
2615  {
2616  char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2617 
2618  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2619  strcpy(s, str);
2620  else
2621  ereport(ERROR,
2622  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2623  errmsg("localized string format value too long")));
2624  }
2625  else
2626  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2627  asc_tolower_z(months_full[tm->tm_mon - 1]));
2628  s += strlen(s);
2629  break;
2630  case DCH_MON:
2632  if (!tm->tm_mon)
2633  break;
2634  if (S_TM(n->suffix))
2635  {
2636  char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2637 
2638  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2639  strcpy(s, str);
2640  else
2641  ereport(ERROR,
2642  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2643  errmsg("localized string format value too long")));
2644  }
2645  else
2646  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2647  s += strlen(s);
2648  break;
2649  case DCH_Mon:
2651  if (!tm->tm_mon)
2652  break;
2653  if (S_TM(n->suffix))
2654  {
2655  char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2656 
2657  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2658  strcpy(s, str);
2659  else
2660  ereport(ERROR,
2661  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2662  errmsg("localized string format value too long")));
2663  }
2664  else
2665  strcpy(s, months[tm->tm_mon - 1]);
2666  s += strlen(s);
2667  break;
2668  case DCH_mon:
2670  if (!tm->tm_mon)
2671  break;
2672  if (S_TM(n->suffix))
2673  {
2674  char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2675 
2676  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2677  strcpy(s, str);
2678  else
2679  ereport(ERROR,
2680  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2681  errmsg("localized string format value too long")));
2682  }
2683  else
2684  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2685  s += strlen(s);
2686  break;
2687  case DCH_MM:
2688  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2689  tm->tm_mon);
2690  if (S_THth(n->suffix))
2691  str_numth(s, s, S_TH_TYPE(n->suffix));
2692  s += strlen(s);
2693  break;
2694  case DCH_DAY:
2696  if (S_TM(n->suffix))
2697  {
2698  char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2699 
2700  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2701  strcpy(s, str);
2702  else
2703  ereport(ERROR,
2704  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2705  errmsg("localized string format value too long")));
2706  }
2707  else
2708  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2709  asc_toupper_z(days[tm->tm_wday]));
2710  s += strlen(s);
2711  break;
2712  case DCH_Day:
2714  if (S_TM(n->suffix))
2715  {
2716  char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2717 
2718  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2719  strcpy(s, str);
2720  else
2721  ereport(ERROR,
2722  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2723  errmsg("localized string format value too long")));
2724  }
2725  else
2726  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2727  days[tm->tm_wday]);
2728  s += strlen(s);
2729  break;
2730  case DCH_day:
2732  if (S_TM(n->suffix))
2733  {
2734  char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
2735 
2736  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2737  strcpy(s, str);
2738  else
2739  ereport(ERROR,
2740  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2741  errmsg("localized string format value too long")));
2742  }
2743  else
2744  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2745  asc_tolower_z(days[tm->tm_wday]));
2746  s += strlen(s);
2747  break;
2748  case DCH_DY:
2750  if (S_TM(n->suffix))
2751  {
2752  char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
2753 
2754  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2755  strcpy(s, str);
2756  else
2757  ereport(ERROR,
2758  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2759  errmsg("localized string format value too long")));
2760  }
2761  else
2762  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
2763  s += strlen(s);
2764  break;
2765  case DCH_Dy:
2767  if (S_TM(n->suffix))
2768  {
2769  char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
2770 
2771  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2772  strcpy(s, str);
2773  else
2774  ereport(ERROR,
2775  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2776  errmsg("localized string format value too long")));
2777  }
2778  else
2779  strcpy(s, days_short[tm->tm_wday]);
2780  s += strlen(s);
2781  break;
2782  case DCH_dy:
2784  if (S_TM(n->suffix))
2785  {
2786  char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
2787 
2788  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2789  strcpy(s, str);
2790  else
2791  ereport(ERROR,
2792  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2793  errmsg("localized string format value too long")));
2794  }
2795  else
2796  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
2797  s += strlen(s);
2798  break;
2799  case DCH_DDD:
2800  case DCH_IDDD:
2801  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
2802  (n->key->id == DCH_DDD) ?
2803  tm->tm_yday :
2804  date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
2805  if (S_THth(n->suffix))
2806  str_numth(s, s, S_TH_TYPE(n->suffix));
2807  s += strlen(s);
2808  break;
2809  case DCH_DD:
2810  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
2811  if (S_THth(n->suffix))
2812  str_numth(s, s, S_TH_TYPE(n->suffix));
2813  s += strlen(s);
2814  break;
2815  case DCH_D:
2817  sprintf(s, "%d", tm->tm_wday + 1);
2818  if (S_THth(n->suffix))
2819  str_numth(s, s, S_TH_TYPE(n->suffix));
2820  s += strlen(s);
2821  break;
2822  case DCH_ID:
2824  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
2825  if (S_THth(n->suffix))
2826  str_numth(s, s, S_TH_TYPE(n->suffix));
2827  s += strlen(s);
2828  break;
2829  case DCH_WW:
2830  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2831  (tm->tm_yday - 1) / 7 + 1);
2832  if (S_THth(n->suffix))
2833  str_numth(s, s, S_TH_TYPE(n->suffix));
2834  s += strlen(s);
2835  break;
2836  case DCH_IW:
2837  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2838  date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
2839  if (S_THth(n->suffix))
2840  str_numth(s, s, S_TH_TYPE(n->suffix));
2841  s += strlen(s);
2842  break;
2843  case DCH_Q:
2844  if (!tm->tm_mon)
2845  break;
2846  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
2847  if (S_THth(n->suffix))
2848  str_numth(s, s, S_TH_TYPE(n->suffix));
2849  s += strlen(s);
2850  break;
2851  case DCH_CC:
2852  if (is_interval) /* straight calculation */
2853  i = tm->tm_year / 100;
2854  else
2855  {
2856  if (tm->tm_year > 0)
2857  /* Century 20 == 1901 - 2000 */
2858  i = (tm->tm_year - 1) / 100 + 1;
2859  else
2860  /* Century 6BC == 600BC - 501BC */
2861  i = tm->tm_year / 100 - 1;
2862  }
2863  if (i <= 99 && i >= -99)
2864  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
2865  else
2866  sprintf(s, "%d", i);
2867  if (S_THth(n->suffix))
2868  str_numth(s, s, S_TH_TYPE(n->suffix));
2869  s += strlen(s);
2870  break;
2871  case DCH_Y_YYY:
2872  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
2873  sprintf(s, "%d,%03d", i,
2874  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
2875  if (S_THth(n->suffix))
2876  str_numth(s, s, S_TH_TYPE(n->suffix));
2877  s += strlen(s);
2878  break;
2879  case DCH_YYYY:
2880  case DCH_IYYY:
2881  sprintf(s, "%0*d",
2882  S_FM(n->suffix) ? 0 :
2883  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
2884  (n->key->id == DCH_YYYY ?
2885  ADJUST_YEAR(tm->tm_year, is_interval) :
2887  tm->tm_mon,
2888  tm->tm_mday),
2889  is_interval)));
2890  if (S_THth(n->suffix))
2891  str_numth(s, s, S_TH_TYPE(n->suffix));
2892  s += strlen(s);
2893  break;
2894  case DCH_YYY:
2895  case DCH_IYY:
2896  sprintf(s, "%0*d",
2897  S_FM(n->suffix) ? 0 :
2898  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
2899  (n->key->id == DCH_YYY ?
2900  ADJUST_YEAR(tm->tm_year, is_interval) :
2902  tm->tm_mon,
2903  tm->tm_mday),
2904  is_interval)) % 1000);
2905  if (S_THth(n->suffix))
2906  str_numth(s, s, S_TH_TYPE(n->suffix));
2907  s += strlen(s);
2908  break;
2909  case DCH_YY:
2910  case DCH_IY:
2911  sprintf(s, "%0*d",
2912  S_FM(n->suffix) ? 0 :
2913  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
2914  (n->key->id == DCH_YY ?
2915  ADJUST_YEAR(tm->tm_year, is_interval) :
2917  tm->tm_mon,
2918  tm->tm_mday),
2919  is_interval)) % 100);
2920  if (S_THth(n->suffix))
2921  str_numth(s, s, S_TH_TYPE(n->suffix));
2922  s += strlen(s);
2923  break;
2924  case DCH_Y:
2925  case DCH_I:
2926  sprintf(s, "%1d",
2927  (n->key->id == DCH_Y ?
2928  ADJUST_YEAR(tm->tm_year, is_interval) :
2930  tm->tm_mon,
2931  tm->tm_mday),
2932  is_interval)) % 10);
2933  if (S_THth(n->suffix))
2934  str_numth(s, s, S_TH_TYPE(n->suffix));
2935  s += strlen(s);
2936  break;
2937  case DCH_RM:
2938  if (!tm->tm_mon)
2939  break;
2940  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2942  s += strlen(s);
2943  break;
2944  case DCH_rm:
2945  if (!tm->tm_mon)
2946  break;
2947  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2949  s += strlen(s);
2950  break;
2951  case DCH_W:
2952  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
2953  if (S_THth(n->suffix))
2954  str_numth(s, s, S_TH_TYPE(n->suffix));
2955  s += strlen(s);
2956  break;
2957  case DCH_J:
2958  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
2959  if (S_THth(n->suffix))
2960  str_numth(s, s, S_TH_TYPE(n->suffix));
2961  s += strlen(s);
2962  break;
2963  }
2964  }
2965 
2966  *s = '\0';
2967 }
#define a_m_STR
Definition: formatting.c:234
#define NODE_TYPE_END
Definition: formatting.c:173
const KeyWord * key
Definition: formatting.c:168
int tm_wday
Definition: pgtime.h:33
#define b_c_STR
Definition: formatting.c:212
#define S_THth(_s)
Definition: formatting.c:515
int tm_hour
Definition: pgtime.h:29
#define BC_STR
Definition: formatting.c:213
#define A_M_STR
Definition: formatting.c:233
static char * str_initcap_z(const char *buff, Oid collid)
Definition: formatting.c:1999
fsec_t fsec
Definition: formatting.c:462
static char * asc_tolower_z(const char *buff)
Definition: formatting.c:2005
#define AD_STR
Definition: formatting.c:208
int errcode(int sqlerrcode)
Definition: elog.c:575
struct pg_tm tm
Definition: formatting.c:461
#define p_m_STR
Definition: formatting.c:239
#define am_STR
Definition: formatting.c:236
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:1987
long int tm_gmtoff
Definition: pgtime.h:36
Definition: pgtime.h:25
char * localized_abbrev_months[12]
Definition: pg_locale.c:96
static char * str_numth(char *dest, char *num, int type)
Definition: formatting.c:1438
static const char *const rm_months_upper[]
Definition: formatting.c:262
int id
Definition: formatting.c:160
#define pm_STR
Definition: formatting.c:241
static struct pg_tm tm
Definition: localtime.c:107
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
void pfree(void *pointer)
Definition: mcxt.c:949
const char *const months[]
Definition: datetime.c:66
#define NODE_TYPE_ACTION
Definition: formatting.c:174
#define ERROR
Definition: elog.h:43
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4092
#define S_FM(_s)
Definition: formatting.c:521
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4146
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
char character
Definition: formatting.c:169
const char *const days[]
Definition: datetime.c:69
#define A_D_STR
Definition: formatting.c:206
#define a_d_STR
Definition: formatting.c:207
#define ereport(elevel, rest)
Definition: elog.h:122
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define bc_STR
Definition: formatting.c:214
#define S_TH_TYPE(_s)
Definition: formatting.c:518
static const char *const months_full[]
Definition: formatting.c:188
int len
Definition: formatting.c:159
char * localized_full_days[7]
Definition: pg_locale.c:95
int date2j(int y, int m, int d)
Definition: datetime.c:292
#define ad_STR
Definition: formatting.c:209
void cache_locale_time(void)
Definition: pg_locale.c:786
#define P_M_STR
Definition: formatting.c:238
static char * asc_toupper_z(const char *buff)
Definition: formatting.c:2011
#define ADJUST_YEAR(year, is_interval)
Definition: formatting.c:204
#define tmtcTzn(_X)
Definition: formatting.c:467
int tm_year
Definition: pgtime.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:797
static char * str_toupper_z(const char *buff, Oid collid)
Definition: formatting.c:1993
#define INVALID_FOR_INTERVAL
Definition: formatting.c:488
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:4203
int i
#define S_TM(_s)
Definition: formatting.c:523
int tm_yday
Definition: pgtime.h:34
#define PM_STR
Definition: formatting.c:240
#define AM_STR
Definition: formatting.c:235
#define TM_SUFFIX_LEN
Definition: formatting.c:529
int tm_sec
Definition: pgtime.h:27
char * localized_full_months[12]
Definition: pg_locale.c:97
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:117
char * localized_abbrev_days[7]
Definition: pg_locale.c:94
int tm_min
Definition: pgtime.h:28
static const char *const rm_months_lower[]
Definition: formatting.c:265
static const char *const days_short[]
Definition: formatting.c:193
#define B_C_STR
Definition: formatting.c:211
static void do_to_timestamp ( text date_txt,
text fmt,
struct pg_tm tm,
fsec_t fsec 
)
static

Definition at line 3608 of file formatting.c.

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

Referenced by to_date(), and to_timestamp().

3610 {
3611  FormatNode *format;
3612  TmFromChar tmfc;
3613  int fmt_len;
3614  char *date_str;
3615  int fmask;
3616 
3617  date_str = text_to_cstring(date_txt);
3618 
3619  ZERO_tmfc(&tmfc);
3620  ZERO_tm(tm);
3621  *fsec = 0;
3622  fmask = 0; /* bit mask for ValidateDate() */
3623 
3624  fmt_len = VARSIZE_ANY_EXHDR(fmt);
3625 
3626  if (fmt_len)
3627  {
3628  char *fmt_str;
3629  bool incache;
3630 
3631  fmt_str = text_to_cstring(fmt);
3632 
3633  if (fmt_len > DCH_CACHE_SIZE)
3634  {
3635  /*
3636  * Allocate new memory if format picture is bigger than static
3637  * cache and do not use cache (call parser always)
3638  */
3639  incache = FALSE;
3640 
3641  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3642 
3643  parse_format(format, fmt_str, DCH_keywords,
3644  DCH_suff, DCH_index, DCH_TYPE, NULL);
3645  }
3646  else
3647  {
3648  /*
3649  * Use cache buffers
3650  */
3651  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3652 
3653  incache = TRUE;
3654  format = ent->format;
3655  }
3656 
3657 #ifdef DEBUG_TO_FROM_CHAR
3658  /* dump_node(format, fmt_len); */
3659  /* dump_index(DCH_keywords, DCH_index); */
3660 #endif
3661 
3662  DCH_from_char(format, date_str, &tmfc);
3663 
3664  pfree(fmt_str);
3665  if (!incache)
3666  pfree(format);
3667  }
3668 
3669  DEBUG_TMFC(&tmfc);
3670 
3671  /*
3672  * Convert to_date/to_timestamp input fields to standard 'tm'
3673  */
3674  if (tmfc.ssss)
3675  {
3676  int x = tmfc.ssss;
3677 
3678  tm->tm_hour = x / SECS_PER_HOUR;
3679  x %= SECS_PER_HOUR;
3680  tm->tm_min = x / SECS_PER_MINUTE;
3681  x %= SECS_PER_MINUTE;
3682  tm->tm_sec = x;
3683  }
3684 
3685  if (tmfc.ss)
3686  tm->tm_sec = tmfc.ss;
3687  if (tmfc.mi)
3688  tm->tm_min = tmfc.mi;
3689  if (tmfc.hh)
3690  tm->tm_hour = tmfc.hh;
3691 
3692  if (tmfc.clock == CLOCK_12_HOUR)
3693  {
3694  if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
3695  ereport(ERROR,
3696  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3697  errmsg("hour \"%d\" is invalid for the 12-hour clock",
3698  tm->tm_hour),
3699  errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
3700 
3701  if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
3702  tm->tm_hour += HOURS_PER_DAY / 2;
3703  else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
3704  tm->tm_hour = 0;
3705  }
3706 
3707  if (tmfc.year)
3708  {
3709  /*
3710  * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
3711  * the year in the given century. Keep in mind that the 21st century
3712  * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
3713  * 600BC to 501BC.
3714  */
3715  if (tmfc.cc && tmfc.yysz <= 2)
3716  {
3717  if (tmfc.bc)
3718  tmfc.cc = -tmfc.cc;
3719  tm->tm_year = tmfc.year % 100;
3720  if (tm->tm_year)
3721  {
3722  if (tmfc.cc >= 0)
3723  tm->tm_year += (tmfc.cc - 1) * 100;
3724  else
3725  tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
3726  }
3727  else
3728  {
3729  /* find century year for dates ending in "00" */
3730  tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
3731  }
3732  }
3733  else
3734  {
3735  /* If a 4-digit year is provided, we use that and ignore CC. */
3736  tm->tm_year = tmfc.year;
3737  if (tmfc.bc && tm->tm_year > 0)
3738  tm->tm_year = -(tm->tm_year - 1);
3739  }
3740  fmask |= DTK_M(YEAR);
3741  }
3742  else if (tmfc.cc)
3743  {
3744  /* use first year of century */
3745  if (tmfc.bc)
3746  tmfc.cc = -tmfc.cc;
3747  if (tmfc.cc >= 0)
3748  /* +1 because 21st century started in 2001 */
3749  tm->tm_year = (tmfc.cc - 1) * 100 + 1;
3750  else
3751  /* +1 because year == 599 is 600 BC */
3752  tm->tm_year = tmfc.cc * 100 + 1;
3753  fmask |= DTK_M(YEAR);
3754  }
3755 
3756  if (tmfc.j)
3757  {
3758  j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3759  fmask |= DTK_DATE_M;
3760  }
3761 
3762  if (tmfc.ww)
3763  {
3764  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3765  {
3766  /*
3767  * If tmfc.d is not set, then the date is left at the beginning of
3768  * the ISO week (Monday).
3769  */
3770  if (tmfc.d)
3771  isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3772  else
3773  isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3774  fmask |= DTK_DATE_M;
3775  }
3776  else
3777  tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
3778  }
3779 
3780  if (tmfc.w)
3781  tmfc.dd = (tmfc.w - 1) * 7 + 1;
3782  if (tmfc.dd)
3783  {
3784  tm->tm_mday = tmfc.dd;
3785  fmask |= DTK_M(DAY);
3786  }
3787  if (tmfc.mm)
3788  {
3789  tm->tm_mon = tmfc.mm;
3790  fmask |= DTK_M(MONTH);
3791  }
3792 
3793  if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
3794  {
3795  /*
3796  * The month and day field have not been set, so we use the
3797  * day-of-year field to populate them. Depending on the date mode,
3798  * this field may be interpreted as a Gregorian day-of-year, or an ISO
3799  * week date day-of-year.
3800  */
3801 
3802  if (!tm->tm_year && !tmfc.bc)
3803  ereport(ERROR,
3804  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3805  errmsg("cannot calculate day of year without year information")));
3806 
3807  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3808  {
3809  int j0; /* zeroth day of the ISO year, in Julian */
3810 
3811  j0 = isoweek2j(tm->tm_year, 1) - 1;
3812 
3813  j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3814  fmask |= DTK_DATE_M;
3815  }
3816  else
3817  {
3818  const int *y;
3819  int i;
3820 
3821  static const int ysum[2][13] = {
3822  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
3823  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
3824 
3825  y = ysum[isleap(tm->tm_year)];
3826 
3827  for (i = 1; i <= MONTHS_PER_YEAR; i++)
3828  {
3829  if (tmfc.ddd <= y[i])
3830  break;
3831  }
3832  if (tm->tm_mon <= 1)
3833  tm->tm_mon = i;
3834 
3835  if (tm->tm_mday <= 1)
3836  tm->tm_mday = tmfc.ddd - y[i - 1];
3837 
3838  fmask |= DTK_M(MONTH) | DTK_M(DAY);
3839  }
3840  }
3841 
3842  if (tmfc.ms)
3843  *fsec += tmfc.ms * 1000;
3844  if (tmfc.us)
3845  *fsec += tmfc.us;
3846 
3847  /* Range-check date fields according to bit mask computed above */
3848  if (fmask != 0)
3849  {
3850  /* We already dealt with AD/BC, so pass isjulian = true */
3851  int dterr = ValidateDate(fmask, true, false, false, tm);
3852 
3853  if (dterr != 0)
3854  {
3855  /*
3856  * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
3857  * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
3858  * irrelevant hint about datestyle.
3859  */
3860  DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3861  }
3862  }
3863 
3864  /* Range-check time fields too */
3865  if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
3866  tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
3867  tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
3868  *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
3869  DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3870 
3871  DEBUG_TM(tm);
3872 
3873  pfree(date_str);
3874 }
#define DEBUG_TM(_X)
Definition: formatting.c:452
struct FormatNode FormatNode
Definition: formatting.c:154
#define DAY
Definition: datetime.h:94
int errhint(const char *fmt,...)
Definition: elog.c:987
void DateTimeParseError(int dterr, const char *str, const char *datatype)
Definition: datetime.c:3765
#define USECS_PER_SEC
Definition: timestamp.h:94
#define YEAR
Definition: datetime.h:93
int tm_hour
Definition: pgtime.h:29
#define isleap(y)
Definition: datetime.h:273
static const KeySuffix DCH_suff[]
Definition: formatting.c:531
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:873
int errcode(int sqlerrcode)
Definition: elog.c:575
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:4074
static void DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
Definition: formatting.c:2978
FromCharDateMode mode
Definition: formatting.c:410
#define DTK_DATE_M
Definition: datetime.h:194
#define MINS_PER_HOUR
Definition: timestamp.h:89
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
void pfree(void *pointer)
Definition: mcxt.c:949
#define DCH_CACHE_SIZE
Definition: formatting.c:374
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define FALSE
Definition: c.h:219
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
Definition: formatting.c:1227
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:379
static DCHCacheEntry * DCH_cache_fetch(const char *str)
Definition: formatting.c:3340
#define ereport(elevel, rest)
Definition: elog.h:122
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:317
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define CLOCK_12_HOUR
Definition: formatting.c:181
#define MONTH
Definition: datetime.h:92
#define DCH_TYPE
Definition: formatting.c:103
void isoweek2date(int woy, int *year, int *mon, int *mday)
Definition: timestamp.c:4061
#define ZERO_tmfc(_X)
Definition: formatting.c:432
int isoweek2j(int year, int week)
Definition: timestamp.c:4041
#define DEBUG_TMFC(_X)
Definition: formatting.c:451
char * text_to_cstring(const text *t)
Definition: varlena.c:182
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
static const KeyWord DCH_keywords[]
Definition: formatting.c:719
int i
#define DTK_M(t)
Definition: datetime.h:190
#define TRUE
Definition: c.h:215
static char format
Definition: pg_basebackup.c:81
int tm_sec
Definition: pgtime.h:27
#define ZERO_tm(_X)
Definition: formatting.c:470
int tm_min
Definition: pgtime.h:28
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2479
static char * fill_str ( char *  str,
int  c,
int  max 
)
static

Definition at line 3883 of file formatting.c.

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

3884 {
3885  memset(str, c, max);
3886  *(str + max) = '\0';
3887  return str;
3888 }
char * c
Datum float4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5485 of file formatting.c.

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

5486 {
5488  text *fmt = PG_GETARG_TEXT_PP(1);
5489  NUMDesc Num;
5490  FormatNode *format;
5491  text *result;
5492  bool shouldFree;
5493  int out_pre_spaces = 0,
5494  sign = 0;
5495  char *numstr,
5496  *orgnum,
5497  *p;
5498 
5500 
5501  if (IS_ROMAN(&Num))
5502  numstr = orgnum = int_to_roman((int) rint(value));
5503  else if (IS_EEEE(&Num))
5504  {
5505  numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5506  if (isnan(value) || is_infinite(value))
5507  {
5508  /*
5509  * Allow 6 characters for the leading sign, the decimal point,
5510  * "e", the exponent's sign and two exponent digits.
5511  */
5512  numstr = (char *) palloc(Num.pre + Num.post + 7);
5513  fill_str(numstr, '#', Num.pre + Num.post + 6);
5514  *numstr = ' ';
5515  *(numstr + Num.pre + 1) = '.';
5516  }
5517  else
5518  {
5519  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5520 
5521  /*
5522  * Swap a leading positive sign for a space.
5523  */
5524  if (*orgnum == '+')
5525  *orgnum = ' ';
5526 
5527  numstr = orgnum;
5528  }
5529  }
5530  else
5531  {
5532  float4 val = value;
5533  int numstr_pre_len;
5534 
5535  if (IS_MULTI(&Num))
5536  {
5537  float multi = pow((double) 10, (double) Num.multi);
5538 
5539  val = value * multi;
5540  Num.pre += Num.multi;
5541  }
5542 
5543  orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
5544  snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
5545  numstr_pre_len = strlen(orgnum);
5546 
5547  /* adjust post digits to fit max float digits */
5548  if (numstr_pre_len >= FLT_DIG)
5549  Num.post = 0;
5550  else if (numstr_pre_len + Num.post > FLT_DIG)
5551  Num.post = FLT_DIG - numstr_pre_len;
5552  snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
5553 
5554  if (*orgnum == '-')
5555  { /* < 0 */
5556  sign = '-';
5557  numstr = orgnum + 1;
5558  }
5559  else
5560  {
5561  sign = '+';
5562  numstr = orgnum;
5563  }
5564 
5565  if ((p = strchr(numstr, '.')))
5566  numstr_pre_len = p - numstr;
5567  else
5568  numstr_pre_len = strlen(numstr);
5569 
5570  /* needs padding? */
5571  if (numstr_pre_len < Num.pre)
5572  out_pre_spaces = Num.pre - numstr_pre_len;
5573  /* overflowed prefix digit format? */
5574  else if (numstr_pre_len > Num.pre)
5575  {
5576  numstr = (char *) palloc(Num.pre + Num.post + 2);
5577  fill_str(numstr, '#', Num.pre + Num.post + 1);
5578  *(numstr + Num.pre) = '.';
5579  }
5580  }
5581 
5583  PG_RETURN_TEXT_P(result);
5584 }
#define MAXDOUBLEWIDTH
Definition: formatting.c:125
#define IS_EEEE(_f)
Definition: formatting.c:357
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXFLOATWIDTH
Definition: formatting.c:124
#define NUM_TOCHAR_finish
Definition: formatting.c:5072
#define IS_ROMAN(_f)
Definition: formatting.c:355
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NUM_TOCHAR_prepare
Definition: formatting.c:5059
#define IS_MULTI(_f)
Definition: formatting.c:356
static struct @121 value
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3883
static char * int_to_roman(int number)
Definition: formatting.c:4081
int pre
Definition: formatting.c:308
double rint(double x)
Definition: rint.c:22
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:245
float float4
Definition: c.h:374
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
int post
Definition: formatting.c:308
int is_infinite(double val)
Definition: float.c:199
void * palloc(Size size)
Definition: mcxt.c:848
int multi
Definition: formatting.c:308
Definition: c.h:433
static char format
Definition: pg_basebackup.c:81
long val
Definition: informix.c:689
Datum float8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5591 of file formatting.c.

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

5592 {
5594  text *fmt = PG_GETARG_TEXT_PP(1);
5595  NUMDesc Num;
5596  FormatNode *format;
5597  text *result;
5598  bool shouldFree;
5599  int out_pre_spaces = 0,
5600  sign = 0;
5601  char *numstr,
5602  *orgnum,
5603  *p;
5604 
5606 
5607  if (IS_ROMAN(&Num))
5608  numstr = orgnum = int_to_roman((int) rint(value));
5609  else if (IS_EEEE(&Num))
5610  {
5611  numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5612  if (isnan(value) || is_infinite(value))
5613  {
5614  /*
5615  * Allow 6 characters for the leading sign, the decimal point,
5616  * "e", the exponent's sign and two exponent digits.
5617  */
5618  numstr = (char *) palloc(Num.pre + Num.post + 7);
5619  fill_str(numstr, '#', Num.pre + Num.post + 6);
5620  *numstr = ' ';
5621  *(numstr + Num.pre + 1) = '.';
5622  }
5623  else
5624  {
5625  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5626 
5627  /*
5628  * Swap a leading positive sign for a space.
5629  */
5630  if (*orgnum == '+')
5631  *orgnum = ' ';
5632 
5633  numstr = orgnum;
5634  }
5635  }
5636  else
5637  {
5638  float8 val = value;
5639  int numstr_pre_len;
5640 
5641  if (IS_MULTI(&Num))
5642  {
5643  double multi = pow((double) 10, (double) Num.multi);
5644 
5645  val = value * multi;
5646  Num.pre += Num.multi;
5647  }
5648  orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5649  numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
5650 
5651  /* adjust post digits to fit max double digits */
5652  if (numstr_pre_len >= DBL_DIG)
5653  Num.post = 0;
5654  else if (numstr_pre_len + Num.post > DBL_DIG)
5655  Num.post = DBL_DIG - numstr_pre_len;
5656  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
5657 
5658  if (*orgnum == '-')
5659  { /* < 0 */
5660  sign = '-';
5661  numstr = orgnum + 1;
5662  }
5663  else
5664  {
5665  sign = '+';
5666  numstr = orgnum;
5667  }
5668 
5669  if ((p = strchr(numstr, '.')))
5670  numstr_pre_len = p - numstr;
5671  else
5672  numstr_pre_len = strlen(numstr);
5673 
5674  /* needs padding? */
5675  if (numstr_pre_len < Num.pre)
5676  out_pre_spaces = Num.pre - numstr_pre_len;
5677  /* overflowed prefix digit format? */
5678  else if (numstr_pre_len > Num.pre)
5679  {
5680  numstr = (char *) palloc(Num.pre + Num.post + 2);
5681  fill_str(numstr, '#', Num.pre + Num.post + 1);
5682  *(numstr + Num.pre) = '.';
5683  }
5684  }
5685 
5687  PG_RETURN_TEXT_P(result);
5688 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
#define MAXDOUBLEWIDTH
Definition: formatting.c:125
#define IS_EEEE(_f)
Definition: formatting.c:357
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define NUM_TOCHAR_finish
Definition: formatting.c:5072
#define IS_ROMAN(_f)
Definition: formatting.c:355
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NUM_TOCHAR_prepare
Definition: formatting.c:5059
double float8
Definition: c.h:375
#define IS_MULTI(_f)
Definition: formatting.c:356
static struct @121 value
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3883
static char * int_to_roman(int number)
Definition: formatting.c:4081
int pre
Definition: formatting.c:308
double rint(double x)
Definition: rint.c:22
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
int post
Definition: formatting.c:308
int is_infinite(double val)
Definition: float.c:199
void * palloc(Size size)
Definition: mcxt.c:848
int multi
Definition: formatting.c:308
Definition: c.h:433
static char format
Definition: pg_basebackup.c:81
long val
Definition: informix.c:689
static int from_char_parse_int ( int *  dest,
char **  src,
FormatNode node 
)
static

Definition at line 2293 of file formatting.c.

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

Referenced by DCH_from_char().

2294 {
2295  return from_char_parse_int_len(dest, src, node->key->len, node);
2296 }
const KeyWord * key
Definition: formatting.c:168
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node)
Definition: formatting.c:2203
int len
Definition: formatting.c:159
static int from_char_parse_int_len ( int *  dest,
char **  src,
const int  len,
FormatNode node 
)
static

Definition at line 2203 of file formatting.c.

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

Referenced by DCH_from_char(), and from_char_parse_int().

2204 {
2205  long result;
2206  char copy[DCH_MAX_ITEM_SIZ + 1];
2207  char *init = *src;
2208  int used;
2209 
2210  /*
2211  * Skip any whitespace before parsing the integer.
2212  */
2213  *src += strspace_len(*src);
2214 
2215  Assert(len <= DCH_MAX_ITEM_SIZ);
2216  used = (int) strlcpy(copy, *src, len + 1);
2217 
2218  if (S_FM(node->suffix) || is_next_separator(node))
2219  {
2220  /*
2221  * This node is in Fill Mode, or the next node is known to be a
2222  * non-digit value, so we just slurp as many characters as we can get.
2223  */
2224  errno = 0;
2225  result = strtol(init, src, 10);
2226  }
2227  else
2228  {
2229  /*
2230  * We need to pull exactly the number of characters given in 'len' out
2231  * of the string, and convert those.
2232  */
2233  char *last;
2234 
2235  if (used < len)
2236  ereport(ERROR,
2237  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2238  errmsg("source string too short for \"%s\" formatting field",
2239  node->key->name),
2240  errdetail("Field requires %d characters, but only %d "
2241  "remain.",
2242  len, used),
2243  errhint("If your source string is not fixed-width, try "
2244  "using the \"FM\" modifier.")));
2245 
2246  errno = 0;
2247  result = strtol(copy, &last, 10);
2248  used = last - copy;
2249 
2250  if (used > 0 && used < len)
2251  ereport(ERROR,
2252  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2253  errmsg("invalid value \"%s\" for \"%s\"",
2254  copy, node->key->name),
2255  errdetail("Field requires %d characters, but only %d "
2256  "could be parsed.", len, used),
2257  errhint("If your source string is not fixed-width, try "
2258  "using the \"FM\" modifier.")));
2259 
2260  *src += used;
2261  }
2262 
2263  if (*src == init)
2264  ereport(ERROR,
2265  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2266  errmsg("invalid value \"%s\" for \"%s\"",
2267  copy, node->key->name),
2268  errdetail("Value must be an integer.")));
2269 
2270  if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2271  ereport(ERROR,
2272  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2273  errmsg("value for \"%s\" in source string is out of range",
2274  node->key->name),
2275  errdetail("Value must be in the range %d to %d.",
2276  INT_MIN, INT_MAX)));
2277 
2278  if (dest != NULL)
2279  from_char_set_int(dest, (int) result, node);
2280  return *src - init;
2281 }
int errhint(const char *fmt,...)
Definition: elog.c:987
const KeyWord * key
Definition: formatting.c:168
static void from_char_set_int(int *dest, const int value, const FormatNode *node)
Definition: formatting.c:2170
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static bool is_next_separator(FormatNode *n)
Definition: formatting.c:2073
#define S_FM(_s)
Definition: formatting.c:521
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: formatting.c:158
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int strspace_len(char *str)
Definition: formatting.c:2129
#define Assert(condition)
Definition: c.h:681
static void init(bool is_no_vacuum)
Definition: pgbench.c:2606
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:117
static int from_char_seq_search ( int *  dest,
char **  src,
const char *const *  array,
int  type,
int  max,
FormatNode node 
)
static

Definition at line 2381 of file formatting.c.

References Assert, DCH_MAX_ITEM_SIZ, ereport, errcode(), errdetail(), errmsg(), ERROR, FormatNode::key, KeyWord::name, seq_search(), and strlcpy().

Referenced by DCH_from_char().

2383 {
2384  int len;
2385 
2386  *dest = seq_search(*src, array, type, max, &len);
2387  if (len <= 0)
2388  {
2389  char copy[DCH_MAX_ITEM_SIZ + 1];
2390 
2391  Assert(max <= DCH_MAX_ITEM_SIZ);
2392  strlcpy(copy, *src, max + 1);
2393 
2394  ereport(ERROR,
2395  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2396  errmsg("invalid value \"%s\" for \"%s\"",
2397  copy, node->key->name),
2398  errdetail("The given value did not match any of the allowed "
2399  "values for this field.")));
2400  }
2401  *src += len;
2402  return len;
2403 }
const KeyWord * key
Definition: formatting.c:168
static int seq_search(char *name, const char *const *array, int type, int max, int *len)
Definition: formatting.c:2303
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: formatting.c:158
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:681
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:117
static void from_char_set_int ( int *  dest,
const int  value,
const FormatNode node 
)
static

Definition at line 2170 of file formatting.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, FormatNode::key, KeyWord::name, and value.

Referenced by DCH_from_char(), and from_char_parse_int_len().

2171 {
2172  if (*dest != 0 && *dest != value)
2173  ereport(ERROR,
2174  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2175  errmsg("conflicting values for \"%s\" field in formatting string",
2176  node->key->name),
2177  errdetail("This value contradicts a previous setting for "
2178  "the same field type.")));
2179  *dest = value;
2180 }
const KeyWord * key
Definition: formatting.c:168
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static struct @121 value
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: formatting.c:158
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void from_char_set_mode ( TmFromChar tmfc,
const FromCharDateMode  mode 
)
static

Definition at line 2148 of file formatting.c.

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

Referenced by DCH_from_char().

2149 {
2150  if (mode != FROM_CHAR_DATE_NONE)
2151  {
2152  if (tmfc->mode == FROM_CHAR_DATE_NONE)
2153  tmfc->mode = mode;
2154  else if (tmfc->mode != mode)
2155  ereport(ERROR,
2156  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2157  errmsg("invalid combination of date conventions"),
2158  errhint("Do not mix Gregorian and ISO week date "
2159  "conventions in a formatting template.")));
2160  }
2161 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
FromCharDateMode mode
Definition: formatting.c:410
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
static char * get_last_relevant_decnum ( char *  num)
static

Definition at line 4212 of file formatting.c.

References elog.

Referenced by NUM_processor().

4213 {
4214  char *result,
4215  *p = strchr(num, '.');
4216 
4217 #ifdef DEBUG_TO_FROM_CHAR
4218  elog(DEBUG_elog_output, "get_last_relevant_decnum()");
4219 #endif
4220 
4221  if (!p)
4222  return NULL;
4223 
4224  result = p;
4225 
4226  while (*(++p))
4227  {
4228  if (*p != '0')
4229  result = p;
4230  }
4231 
4232  return result;
4233 }
#define elog
Definition: elog.h:219
static const char * get_th ( char *  num,
int  type 
)
static

Definition at line 1392 of file formatting.c.

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

Referenced by NUM_processor(), and str_numth().

1393 {
1394  int len = strlen(num),
1395  last,
1396  seclast;
1397 
1398  last = *(num + (len - 1));
1399  if (!isdigit((unsigned char) last))
1400  ereport(ERROR,
1401  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1402  errmsg("\"%s\" is not a number", num)));
1403 
1404  /*
1405  * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
1406  * 'ST/st', 'ND/nd', 'RD/rd', respectively
1407  */
1408  if ((len > 1) && ((seclast = num[len - 2]) == '1'))
1409  last = 0;
1410 
1411  switch (last)
1412  {
1413  case '1':
1414  if (type == TH_UPPER)
1415  return numTH[0];
1416  return numth[0];
1417  case '2':
1418  if (type == TH_UPPER)
1419  return numTH[1];
1420  return numth[1];
1421  case '3':
1422  if (type == TH_UPPER)
1423  return numTH[2];
1424  return numth[2];
1425  default:
1426  if (type == TH_UPPER)
1427  return numTH[3];
1428  return numth[3];
1429  }
1430 }
int errcode(int sqlerrcode)
Definition: elog.c:575
static const char *const numTH[]
Definition: formatting.c:280
#define TH_UPPER
Definition: formatting.c:299
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static const char *const numth[]
Definition: formatting.c:281
int errmsg(const char *fmt,...)
Definition: elog.c:797
static const KeyWord * index_seq_search ( const char *  str,
const KeyWord kw,
const int *  index 
)
static

Definition at line 1008 of file formatting.c.

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

Referenced by parse_format().

1009 {
1010  int poz;
1011 
1012  if (!KeyWord_INDEX_FILTER(*str))
1013  return NULL;
1014 
1015  if ((poz = *(index + (*str - ' '))) > -1)
1016  {
1017  const KeyWord *k = kw + poz;
1018 
1019  do
1020  {
1021  if (strncmp(str, k->name, k->len) == 0)
1022  return k;
1023  k++;
1024  if (!k->name)
1025  return NULL;
1026  } while (*str == *k->name);
1027  }
1028  return NULL;
1029 }
Definition: type.h:89
const char * name
Definition: formatting.c:158
int len
Definition: formatting.c:159
#define KeyWord_INDEX_FILTER(_c)
Definition: formatting.c:111
Datum int4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5280 of file formatting.c.

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

5281 {
5283  text *fmt = PG_GETARG_TEXT_PP(1);
5284  NUMDesc Num;
5285  FormatNode *format;
5286  text *result;
5287  bool shouldFree;
5288  int out_pre_spaces = 0,
5289  sign = 0;
5290  char *numstr,
5291  *orgnum;
5292 
5294 
5295  /*
5296  * On DateType depend part (int32)
5297  */
5298  if (IS_ROMAN(&Num))
5299  numstr = orgnum = int_to_roman(value);
5300  else if (IS_EEEE(&Num))
5301  {
5302  /* we can do it easily because float8 won't lose any precision */
5303  float8 val = (float8) value;
5304 
5305  orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5306  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
5307 
5308  /*
5309  * Swap a leading positive sign for a space.
5310  */
5311  if (*orgnum == '+')
5312  *orgnum = ' ';
5313 
5314  numstr = orgnum;
5315  }
5316  else
5317  {
5318  int numstr_pre_len;
5319 
5320  if (IS_MULTI(&Num))
5321  {
5323  Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
5324  Num.pre += Num.multi;
5325  }
5326  else
5327  {
5329  Int32GetDatum(value)));
5330  }
5331 
5332  if (*orgnum == '-')
5333  {
5334  sign = '-';
5335  orgnum++;
5336  }
5337  else
5338  sign = '+';
5339 
5340  numstr_pre_len = strlen(orgnum);
5341 
5342  /* post-decimal digits? Pad out with zeros. */
5343  if (Num.post)
5344  {
5345  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5346  strcpy(numstr, orgnum);
5347  *(numstr + numstr_pre_len) = '.';
5348  memset(numstr + numstr_pre_len + 1, '0', Num.post);
5349  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
5350  }
5351  else
5352  numstr = orgnum;
5353 
5354  /* needs padding? */
5355  if (numstr_pre_len < Num.pre)
5356  out_pre_spaces = Num.pre - numstr_pre_len;
5357  /* overflowed prefix digit format? */
5358  else if (numstr_pre_len > Num.pre)
5359  {
5360  numstr = (char *) palloc(Num.pre + Num.post + 2);
5361  fill_str(numstr, '#', Num.pre + Num.post + 1);
5362  *(numstr + Num.pre) = '.';
5363  }
5364  }
5365 
5367  PG_RETURN_TEXT_P(result);
5368 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define MAXDOUBLEWIDTH
Definition: formatting.c:125
#define IS_EEEE(_f)
Definition: formatting.c:357
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define NUM_TOCHAR_finish
Definition: formatting.c:5072
#define IS_ROMAN(_f)
Definition: formatting.c:355
signed int int32
Definition: c.h:246
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NUM_TOCHAR_prepare
Definition: formatting.c:5059
double float8
Definition: c.h:375
#define DatumGetCString(X)
Definition: postgres.h:572
#define IS_MULTI(_f)
Definition: formatting.c:356
static struct @121 value
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3883
static char * int_to_roman(int number)
Definition: formatting.c:4081
int pre
Definition: formatting.c:308
Datum int4out(PG_FUNCTION_ARGS)
Definition: int.c:277
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
int post
Definition: formatting.c:308
#define Int32GetDatum(X)
Definition: postgres.h:485
void * palloc(Size size)
Definition: mcxt.c:848
int multi
Definition: formatting.c:308
Definition: c.h:433
static char format
Definition: pg_basebackup.c:81
long val
Definition: informix.c:689
Datum int8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5375 of file formatting.c.

References DatumGetCString, DatumGetInt32, DatumGetInt64, DatumGetNumeric, DirectFunctionCall1, DirectFunctionCall2, dtoi8(), fill_str(), Float8GetDatum(), format, Int64GetDatum(), int84(), int8_numeric(), 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, val, and value.

5376 {
5377  int64 value = PG_GETARG_INT64(0);
5378  text *fmt = PG_GETARG_TEXT_PP(1);
5379  NUMDesc Num;
5380  FormatNode *format;
5381  text *result;
5382  bool shouldFree;
5383  int out_pre_spaces = 0,
5384  sign = 0;
5385  char *numstr,
5386  *orgnum;
5387 
5389 
5390  /*
5391  * On DateType depend part (int32)
5392  */
5393  if (IS_ROMAN(&Num))
5394  {
5395  /* Currently don't support int8 conversion to roman... */
5396  numstr = orgnum = int_to_roman(DatumGetInt32(
5398  }
5399  else if (IS_EEEE(&Num))
5400  {
5401  /* to avoid loss of precision, must go via numeric not float8 */
5402  Numeric val;
5403 
5405  Int64GetDatum(value)));
5406  orgnum = numeric_out_sci(val, Num.post);
5407 
5408  /*
5409  * numeric_out_sci() does not emit a sign for positive numbers. We
5410  * need to add a space in this case so that positive and negative
5411  * numbers are aligned. We don't have to worry about NaN here.
5412  */
5413  if (*orgnum != '-')
5414  {
5415  numstr = (char *) palloc(strlen(orgnum) + 2);
5416  *numstr = ' ';
5417  strcpy(numstr + 1, orgnum);
5418  }
5419  else
5420  {
5421  numstr = orgnum;
5422  }
5423  }
5424  else
5425  {
5426  int numstr_pre_len;
5427 
5428  if (IS_MULTI(&Num))
5429  {
5430  double multi = pow((double) 10, (double) Num.multi);
5431 
5433  Int64GetDatum(value),
5435  Float8GetDatum(multi))));
5436  Num.pre += Num.multi;
5437  }
5438 
5440  Int64GetDatum(value)));
5441 
5442  if (*orgnum == '-')
5443  {
5444  sign = '-';
5445  orgnum++;
5446  }
5447  else
5448  sign = '+';
5449 
5450  numstr_pre_len = strlen(orgnum);
5451 
5452  /* post-decimal digits? Pad out with zeros. */
5453  if (Num.post)
5454  {
5455  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5456  strcpy(numstr, orgnum);
5457  *(numstr + numstr_pre_len) = '.';
5458  memset(numstr + numstr_pre_len + 1, '0', Num.post);
5459  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
5460  }
5461  else
5462  numstr = orgnum;
5463 
5464  /* needs padding? */
5465  if (numstr_pre_len < Num.pre)
5466  out_pre_spaces = Num.pre - numstr_pre_len;
5467  /* overflowed prefix digit format? */
5468  else if (numstr_pre_len > Num.pre)
5469  {
5470  numstr = (char *) palloc(Num.pre + Num.post + 2);
5471  fill_str(numstr, '#', Num.pre + Num.post + 1);
5472  *(numstr + Num.pre) = '.';
5473  }
5474  }
5475 
5477  PG_RETURN_TEXT_P(result);
5478 }
#define DatumGetInt32(X)
Definition: postgres.h:478
#define IS_EEEE(_f)
Definition: formatting.c:357
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define NUM_TOCHAR_finish
Definition: formatting.c:5072
#define IS_ROMAN(_f)
Definition: formatting.c:355
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3038
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1810
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define NUM_TOCHAR_prepare
Definition: formatting.c:5059
#define DatumGetCString(X)
Definition: postgres.h:572
#define IS_MULTI(_f)
Definition: formatting.c:356
static struct @121 value
#define DatumGetInt64(X)
Definition: postgres.h:613
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3883
Datum int8mul(PG_FUNCTION_ARGS)
Definition: int8.c:555
static char * int_to_roman(int number)
Definition: formatting.c:4081
Datum dtoi8(PG_FUNCTION_ARGS)
Definition: int8.c:1343
int pre
Definition: formatting.c:308
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1786
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
int post
Definition: formatting.c:308
#define DatumGetNumeric(X)
Definition: numeric.h:49
Datum int84(PG_FUNCTION_ARGS)
Definition: int8.c:1287
void * palloc(Size size)
Definition: mcxt.c:848
int multi
Definition: formatting.c:308
Definition: c.h:433
static char format
Definition: pg_basebackup.c:81
char * numeric_out_sci(Numeric num, int scale)
Definition: numeric.c:729
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
long val
Definition: informix.c:689
Datum int8out(PG_FUNCTION_ARGS)
Definition: int8.c:158
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
static char * int_to_roman ( int  number)
static

Definition at line 4081 of file formatting.c.

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

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

4082 {
4083  int len = 0,
4084  num = 0;
4085  char *p = NULL,
4086  *result,
4087  numstr[5];
4088 
4089  result = (char *) palloc(16);
4090  *result = '\0';
4091 
4092  if (number > 3999 || number < 1)
4093  {
4094  fill_str(result, '#', 15);
4095  return result;
4096  }
4097  len = snprintf(numstr, sizeof(numstr), "%d", number);
4098 
4099  for (p = numstr; *p != '\0'; p++, --len)
4100  {
4101  num = *p - 49; /* 48 ascii + 1 */
4102  if (num < 0)
4103  continue;
4104 
4105  if (len > 3)
4106  {
4107  while (num-- != -1)
4108  strcat(result, "M");
4109  }
4110  else
4111  {
4112  if (len == 3)
4113  strcat(result, rm100[num]);
4114  else if (len == 2)
4115  strcat(result, rm10[num]);
4116  else if (len == 1)
4117  strcat(result, rm1[num]);
4118  }
4119  }
4120  return result;
4121 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static const char *const rm10[]
Definition: formatting.c:273
static const char *const rm1[]
Definition: formatting.c:272
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3883
static const char *const rm100[]
Definition: formatting.c:274
void * palloc(Size size)
Definition: mcxt.c:848
Datum interval_to_char ( PG_FUNCTION_ARGS  )

Definition at line 3504 of file formatting.c.

References datetime_to_char_body(), DAYS_PER_MONTH, interval2tm(), MONTHS_PER_YEAR, PG_GET_COLLATION, PG_GETARG_INTERVAL_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_yday, pg_tm::tm_year, tmtcFsec, tmtcTm, VARSIZE_ANY_EXHDR, and ZERO_tmtc.

3505 {
3506  Interval *it = PG_GETARG_INTERVAL_P(0);
3507  text *fmt = PG_GETARG_TEXT_PP(1),
3508  *res;
3509  TmToChar tmtc;
3510  struct pg_tm *tm;
3511 
3512  if (VARSIZE_ANY_EXHDR(fmt) <= 0)
3513  PG_RETURN_NULL();
3514 
3515  ZERO_tmtc(&tmtc);
3516  tm = tmtcTm(&tmtc);
3517 
3518  if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
3519  PG_RETURN_NULL();
3520 
3521  /* wday is meaningless, yday approximates the total span in days */
3522  tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
3523 
3524  if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
3525  PG_RETURN_NULL();
3526 
3527  PG_RETURN_TEXT_P(res);
3528 }
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:37
static text * datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
Definition: formatting.c:3367
#define ZERO_tmtc(_X)
Definition: formatting.c:477
Definition: pgtime.h:25
#define PG_GET_COLLATION()
Definition: fmgr.h:163
#define tmtcFsec(_X)
Definition: formatting.c:468
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static struct pg_tm tm
Definition: localtime.c:107
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
int interval2tm(Interval span, struct pg_tm *tm, fsec_t *fsec)
Definition: timestamp.c:1902
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define DAYS_PER_MONTH
Definition: timestamp.h:77
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int tm_yday
Definition: pgtime.h:34
Definition: c.h:433
#define tmtcTm(_X)
Definition: formatting.c:466
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static bool is_next_separator ( FormatNode n)
static

Definition at line 2073 of file formatting.c.

References FormatNode::character, FALSE, KeyWord::is_digit, FormatNode::key, NODE_TYPE_ACTION, NODE_TYPE_END, S_THth, FormatNode::suffix, TRUE, and FormatNode::type.

Referenced by from_char_parse_int_len().

2074 {
2075  if (n->type == NODE_TYPE_END)
2076  return FALSE;
2077 
2078  if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
2079  return TRUE;
2080 
2081  /*
2082  * Next node
2083  */
2084  n++;
2085 
2086  /* end of format string is treated like a non-digit separator */
2087  if (n->type == NODE_TYPE_END)
2088  return TRUE;
2089 
2090  if (n->type == NODE_TYPE_ACTION)
2091  {
2092  if (n->key->is_digit)
2093  return FALSE;
2094 
2095  return TRUE;
2096  }
2097  else if (isdigit((unsigned char) n->character))
2098  return FALSE;
2099 
2100  return TRUE; /* some non-digit input (separator) */
2101 }
#define NODE_TYPE_END
Definition: formatting.c:173
const KeyWord * key
Definition: formatting.c:168
#define S_THth(_s)
Definition: formatting.c:515
#define NODE_TYPE_ACTION
Definition: formatting.c:174
#define FALSE
Definition: c.h:219
char character
Definition: formatting.c:169
#define TRUE
Definition: c.h:215
bool is_digit
Definition: formatting.c:161
static FormatNode * NUM_cache ( int  len,
NUMDesc Num,
text pars_str,
bool shouldFree 
)
static

Definition at line 4023 of file formatting.c.

References NUMDesc::flag, format, NUMCacheEntry::format, NUMDesc::lsign, NUMDesc::multi, NUMDesc::need_locale, NUMCacheEntry::Num, NUM_cache_fetch(), NUM_CACHE_SIZE, NUM_index, NUM_TYPE, palloc(), parse_format(), pfree(), NUMDesc::post, NUMDesc::pre, NUMDesc::pre_lsign_num, text_to_cstring(), NUMDesc::zero_end, NUMDesc::zero_start, and zeroize_NUM.

Referenced by numeric_to_number().

4024 {
4025  FormatNode *format = NULL;
4026  char *str;
4027 
4028  str = text_to_cstring(pars_str);
4029 
4030  if (len > NUM_CACHE_SIZE)
4031  {
4032  /*
4033  * Allocate new memory if format picture is bigger than static cache
4034  * and do not use cache (call parser always)
4035  */
4036  format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
4037 
4038  *shouldFree = true;
4039 
4040  zeroize_NUM(Num);
4041 
4042  parse_format(format, str, NUM_keywords,
4043  NULL, NUM_index, NUM_TYPE, Num);
4044  }
4045  else
4046  {
4047  /*
4048  * Use cache buffers
4049  */
4050  NUMCacheEntry *ent = NUM_cache_fetch(str);
4051 
4052  *shouldFree = false;
4053 
4054  format = ent->format;
4055 
4056  /*
4057  * Copy cache to used struct
4058  */
4059  Num->flag = ent->Num.flag;
4060  Num->lsign = ent->Num.lsign;
4061  Num->pre = ent->Num.pre;
4062  Num->post = ent->Num.post;
4063  Num->pre_lsign_num = ent->Num.pre_lsign_num;
4064  Num->need_locale = ent->Num.need_locale;
4065  Num->multi = ent->Num.multi;
4066  Num->zero_start = ent->Num.zero_start;
4067  Num->zero_end = ent->Num.zero_end;
4068  }
4069 
4070 #ifdef DEBUG_TO_FROM_CHAR
4071  /* dump_node(format, len); */
4072  dump_index(NUM_keywords, NUM_index);
4073 #endif
4074 
4075  pfree(str);
4076  return format;
4077 }
NUMDesc Num
Definition: formatting.c:391
int need_locale
Definition: formatting.c:308
struct FormatNode FormatNode
Definition: formatting.c:154
int flag
Definition: formatting.c:308
#define NUM_CACHE_SIZE
Definition: formatting.c:372
void pfree(void *pointer)
Definition: mcxt.c:949
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
Definition: formatting.c:1227
int pre
Definition: formatting.c:308
#define NUM_TYPE
Definition: formatting.c:104
static NUMCacheEntry * NUM_cache_fetch(const char *str)
Definition: formatting.c:3995
int post
Definition: formatting.c:308
int zero_end
Definition: formatting.c:308
int pre_lsign_num
Definition: formatting.c:308
static const KeyWord NUM_keywords[]
Definition: formatting.c:825
char * text_to_cstring(const text *t)
Definition: varlena.c:182
void * palloc(Size size)
Definition: mcxt.c:848
FormatNode format[NUM_CACHE_SIZE+1]
Definition: formatting.c:387
int multi
Definition: formatting.c:308
int lsign
Definition: formatting.c:308
int zero_start
Definition: formatting.c:308
static char format
Definition: pg_basebackup.c:81
static const int NUM_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:897
#define zeroize_NUM(_n)
Definition: formatting.c:3890
static NUMCacheEntry * NUM_cache_fetch ( const char *  str)
static

Definition at line 3995 of file formatting.c.

References NUMCacheEntry::format, NUMCacheEntry::Num, NUM_cache_getnew(), NUM_cache_search(), NUM_index, NUM_TYPE, parse_format(), NUMCacheEntry::valid, and zeroize_NUM.

Referenced by NUM_cache().

3996 {
3997  NUMCacheEntry *ent;
3998 
3999  if ((ent = NUM_cache_search(str)) == NULL)
4000  {
4001  /*
4002  * Not in the cache, must run parser and save a new format-picture to
4003  * the cache. Do not mark the cache entry valid until parsing
4004  * succeeds.
4005  */
4006  ent = NUM_cache_getnew(str);
4007 
4008  zeroize_NUM(&ent->Num);
4009 
4010  parse_format(ent->format, str, NUM_keywords,
4011  NULL, NUM_index, NUM_TYPE, &ent->Num);
4012 
4013  ent->valid = true;
4014  }
4015  return ent;
4016 }
static NUMCacheEntry * NUM_cache_getnew(const char *str)
Definition: formatting.c:3905
NUMDesc Num
Definition: formatting.c:391
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
Definition: formatting.c:1227
static NUMCacheEntry * NUM_cache_search(const char *str)
Definition: formatting.c:3967
#define NUM_TYPE
Definition: formatting.c:104
static const KeyWord NUM_keywords[]
Definition: formatting.c:825
FormatNode format[NUM_CACHE_SIZE+1]
Definition: formatting.c:387
static const int NUM_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:897
#define zeroize_NUM(_n)
Definition: formatting.c:3890
static NUMCacheEntry * NUM_cache_getnew ( const char *  str)
static

Definition at line 3905 of file formatting.c.

References NUMCacheEntry::age, elog, n_NUMCache, NUM_CACHE_ENTRIES, NUM_CACHE_SIZE, NUMCounter, NUMCacheEntry::str, StrNCpy, and NUMCacheEntry::valid.

Referenced by NUM_cache_fetch().

3906 {
3907  NUMCacheEntry *ent;
3908 
3909  /* counter overflow check - paranoia? */
3910  if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
3911  {
3912  NUMCounter = 0;
3913 
3914  for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
3915  ent->age = (++NUMCounter);
3916  }
3917 
3918  /*
3919  * If cache is full, remove oldest entry (or recycle first not-valid one)
3920  */
3922  {
3923  NUMCacheEntry *old = NUMCache + 0;
3924 
3925 #ifdef DEBUG_TO_FROM_CHAR
3926  elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
3927 #endif
3928  if (old->valid)
3929  {
3930  for (ent = NUMCache + 1; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
3931  {
3932  if (!ent->valid)
3933  {
3934  old = ent;
3935  break;
3936  }
3937  if (ent->age < old->age)
3938  old = ent;
3939  }
3940  }
3941 #ifdef DEBUG_TO_FROM_CHAR
3942  elog(DEBUG_elog_output, "OLD: \"%s\" AGE: %d", old->str, old->age);
3943 #endif
3944  old->valid = false;
3945  StrNCpy(old->str, str, NUM_CACHE_SIZE + 1);
3946  old->age = (++NUMCounter);
3947  /* caller is expected to fill format and Num, then set valid */
3948  return old;
3949  }
3950  else
3951  {
3952 #ifdef DEBUG_TO_FROM_CHAR
3953  elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
3954 #endif
3955  ent = NUMCache + n_NUMCache;
3956  ent->valid = false;
3957  StrNCpy(ent->str, str, NUM_CACHE_SIZE + 1);
3958  ent->age = (++NUMCounter);
3959  /* caller is expected to fill format and Num, then set valid */
3960  ++n_NUMCache;
3961  return ent;
3962  }
3963 }
static NUMCacheEntry NUMCache[NUM_CACHE_ENTRIES]
Definition: formatting.c:400
#define NUM_CACHE_ENTRIES
Definition: formatting.c:373
char str[NUM_CACHE_SIZE+1]
Definition: formatting.c:388
#define NUM_CACHE_SIZE
Definition: formatting.c:372
static int NUMCounter
Definition: formatting.c:402
static int n_NUMCache
Definition: formatting.c:401
#define StrNCpy(dst, src, len)
Definition: c.h:836
#define elog
Definition: elog.h:219