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

Referenced by DCH_to_char().

#define a_d_STR   "a.d."

Definition at line 203 of file formatting.c.

Referenced by DCH_to_char().

#define A_M_STR   "A.M."

Definition at line 229 of file formatting.c.

Referenced by DCH_to_char().

#define a_m_STR   "a.m."

Definition at line 230 of file formatting.c.

Referenced by DCH_to_char().

#define AD_STR   "AD"

Definition at line 204 of file formatting.c.

Referenced by DCH_to_char().

#define ad_STR   "ad"

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

Referenced by DCH_to_char().

#define ALL_LOWER   3 /* name */

Definition at line 285 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

#define ALL_UPPER   2 /* NAME */

Definition at line 284 of file formatting.c.

Referenced by DCH_from_char(), and seq_search().

#define AM_STR   "AM"

Definition at line 231 of file formatting.c.

Referenced by DCH_to_char().

#define am_STR   "am"

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

Referenced by DCH_to_char().

#define b_c_STR   "b.c."

Definition at line 208 of file formatting.c.

Referenced by DCH_to_char().

#define BC_STR   "BC"

Definition at line 209 of file formatting.c.

Referenced by DCH_to_char().

#define bc_STR   "bc"

Definition at line 210 of file formatting.c.

Referenced by DCH_to_char().

#define CLOCK_12_HOUR   1

Definition at line 177 of file formatting.c.

Referenced by DCH_from_char(), and do_to_timestamp().

#define CLOCK_24_HOUR   0

Definition at line 176 of file formatting.c.

#define DCH_CACHE_ENTRIES   20

Definition at line 371 of file formatting.c.

Referenced by DCH_cache_getnew(), and DCH_cache_search().

#define DCH_CACHE_SIZE   128

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

#define DCH_S_SP   0x08

Definition at line 504 of file formatting.c.

#define DCH_S_TH   0x02

Definition at line 502 of file formatting.c.

#define DCH_S_th   0x04

Definition at line 503 of file formatting.c.

#define DCH_S_TM   0x10

Definition at line 505 of file formatting.c.

#define DCH_TYPE   1 /* DATE-TIME version */

Definition at line 99 of file formatting.c.

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

#define DEBUG_TM (   _X)

Definition at line 448 of file formatting.c.

Referenced by do_to_timestamp().

#define DEBUG_TMFC (   _X)

Definition at line 447 of file formatting.c.

Referenced by do_to_timestamp().

#define FULL_SIZ   0

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

Referenced by DCH_to_char().

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

Definition at line 345 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 346 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 343 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 348 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 350 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:344
#define FALSE
Definition: c.h:218

Definition at line 4413 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 344 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 107 of file formatting.c.

Referenced by index_seq_search().

#define KeyWord_INDEX_SIZE   ('~' - ' ')

Definition at line 106 of file formatting.c.

#define MAX_DAY_LEN   9

Definition at line 291 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_DY_LEN   3

Definition at line 292 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_MON_LEN   3

Definition at line 290 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_MONTH_LEN   9

Definition at line 289 of file formatting.c.

Referenced by DCH_from_char().

#define MAX_RM_LEN   4

Definition at line 293 of file formatting.c.

Referenced by DCH_from_char().

#define MAXDOUBLEWIDTH   500

Definition at line 121 of file formatting.c.

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

#define MAXFLOATWIDTH   60

Definition at line 120 of file formatting.c.

Referenced by float4_to_char().

#define NODE_TYPE_ACTION   2
#define NODE_TYPE_CHAR   3

Definition at line 171 of file formatting.c.

Referenced by parse_format().

#define NODE_TYPE_END   1
#define NUM_CACHE_ENTRIES   20

Definition at line 369 of file formatting.c.

Referenced by NUM_cache_getnew(), and NUM_cache_search().

#define NUM_CACHE_SIZE   64

Definition at line 368 of file formatting.c.

Referenced by NUM_cache(), and NUM_cache_getnew().

#define NUM_F_BLANK   (1 << 4)

Definition at line 322 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_BRACKET   (1 << 7)

Definition at line 325 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_DECIMAL   (1 << 1)

Definition at line 319 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_EEEE   (1 << 14)

Definition at line 332 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_FILLMODE   (1 << 5)

Definition at line 323 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_LDECIMAL   (1 << 2)

Definition at line 320 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_LSIGN   (1 << 6)

Definition at line 324 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_MINUS   (1 << 8)

Definition at line 326 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_MINUS_POST   (1 << 13)

Definition at line 331 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_MULTI   (1 << 11)

Definition at line 329 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_PLUS   (1 << 9)

Definition at line 327 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_PLUS_POST   (1 << 12)

Definition at line 330 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_F_ROMAN   (1 << 10)

Definition at line 328 of file formatting.c.

Referenced by NUM_processor(), and NUMDesc_prepare().

#define NUM_F_ZERO   (1 << 3)

Definition at line 321 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_LSIGN_NONE   0

Definition at line 336 of file formatting.c.

Referenced by NUMDesc_prepare().

#define NUM_LSIGN_POST   1

Definition at line 335 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 114 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:305
#define VARHDRSZ
Definition: c.h:441
#define PG_GET_COLLATION()
Definition: fmgr.h:155
void pfree(void *pointer)
Definition: mcxt.c:992
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:4611
static char format
Definition: pg_basebackup.c:83
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330

Definition at line 5038 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:441
static FormatNode * NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
Definition: formatting.c:3989
void * palloc0(Size size)
Definition: mcxt.c:920
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define NUM_MAX_ITEM_SIZ
Definition: formatting.c:114
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
Definition: c.h:435
static char format
Definition: pg_basebackup.c:83

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

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

#define ONE_UPPER   1 /* Name */

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

Referenced by DCH_to_char().

#define p_m_STR   "p.m."

Definition at line 235 of file formatting.c.

Referenced by DCH_to_char().

#define PM_STR   "PM"

Definition at line 236 of file formatting.c.

Referenced by DCH_to_char().

#define pm_STR   "pm"

Definition at line 237 of file formatting.c.

Referenced by DCH_to_char().

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

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

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

Definition at line 512 of file formatting.c.

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

Definition at line 513 of file formatting.c.

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

Definition at line 514 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 511 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 519 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:511

Definition at line 1969 of file formatting.c.

Referenced by DCH_from_char().

#define SUFFTYPE_POSTFIX   2

Definition at line 174 of file formatting.c.

Referenced by parse_format().

#define SUFFTYPE_PREFIX   1

Definition at line 173 of file formatting.c.

Referenced by parse_format().

#define TH_LOWER   2

Definition at line 296 of file formatting.c.

Referenced by NUM_processor().

#define TH_UPPER   1

Definition at line 295 of file formatting.c.

Referenced by get_th(), and NUM_processor().

#define TM_SUFFIX_LEN   2

Definition at line 525 of file formatting.c.

Referenced by DCH_to_char().

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

Definition at line 464 of file formatting.c.

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

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

Definition at line 462 of file formatting.c.

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

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

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

Referenced by do_to_timestamp().

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

Definition at line 428 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:464
#define NULL
Definition: c.h:226
#define tmtcTzn(_X)
Definition: formatting.c:463
#define tmtcTm(_X)
Definition: formatting.c:462
#define ZERO_tm(_X)
Definition: formatting.c:466

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

Referenced by NUM_cache(), and NUM_cache_fetch().

Typedef Documentation

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

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

Definition at line 143 of file formatting.c.

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

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

Function Documentation

static int adjust_partial_year_to_2020 ( int  year)
static

Definition at line 2049 of file formatting.c.

Referenced by DCH_from_char().

2050 {
2051  /*
2052  * Adjust all dates toward 2020; this is effectively what happens when we
2053  * assume '70' is 1970 and '69' is 2069.
2054  */
2055  /* Force 0-69 into the 2000's */
2056  if (year < 70)
2057  return year + 2000;
2058  /* Force 70-99 into the 1900's */
2059  else if (year < 100)
2060  return year + 1900;
2061  /* Force 100-519 into the 2000's */
2062  else if (year < 520)
2063  return year + 2000;
2064  /* Force 520-999 into the 1000's */
2065  else if (year < 1000)
2066  return year + 1000;
2067  else
2068  return year;
2069 }
char* asc_initcap ( const char *  buff,
size_t  nbytes 
)

Definition at line 1900 of file formatting.c.

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

Referenced by str_initcap().

1901 {
1902  char *result;
1903  char *p;
1904  int wasalnum = false;
1905 
1906  if (!buff)
1907  return NULL;
1908 
1909  result = pnstrdup(buff, nbytes);
1910 
1911  for (p = result; *p; p++)
1912  {
1913  char c;
1914 
1915  if (wasalnum)
1916  *p = c = pg_ascii_tolower((unsigned char) *p);
1917  else
1918  *p = c = pg_ascii_toupper((unsigned char) *p);
1919  /* we don't trust isalnum() here */
1920  wasalnum = ((c >= 'A' && c <= 'Z') ||
1921  (c >= 'a' && c <= 'z') ||
1922  (c >= '0' && c <= '9'));
1923  }
1924 
1925  return result;
1926 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1176
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
#define NULL
Definition: c.h:226
char* asc_tolower ( const char *  buff,
size_t  nbytes 
)

Definition at line 1854 of file formatting.c.

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

Referenced by asc_tolower_z(), and str_tolower().

1855 {
1856  char *result;
1857  char *p;
1858 
1859  if (!buff)
1860  return NULL;
1861 
1862  result = pnstrdup(buff, nbytes);
1863 
1864  for (p = result; *p; p++)
1865  *p = pg_ascii_tolower((unsigned char) *p);
1866 
1867  return result;
1868 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1176
unsigned char pg_ascii_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:146
#define NULL
Definition: c.h:226
static char* asc_tolower_z ( const char *  buff)
static

Definition at line 1949 of file formatting.c.

References asc_tolower().

Referenced by DCH_to_char(), and NUM_processor().

1950 {
1951  return asc_tolower(buff, strlen(buff));
1952 }
char * asc_tolower(const char *buff, size_t nbytes)
Definition: formatting.c:1854
char* asc_toupper ( const char *  buff,
size_t  nbytes 
)

Definition at line 1877 of file formatting.c.

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

Referenced by asc_toupper_z(), and str_toupper().

1878 {
1879  char *result;
1880  char *p;
1881 
1882  if (!buff)
1883  return NULL;
1884 
1885  result = pnstrdup(buff, nbytes);
1886 
1887  for (p = result; *p; p++)
1888  *p = pg_ascii_toupper((unsigned char) *p);
1889 
1890  return result;
1891 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1176
unsigned char pg_ascii_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:135
#define NULL
Definition: c.h:226
static char* asc_toupper_z ( const char *  buff)
static

Definition at line 1955 of file formatting.c.

References asc_toupper().

Referenced by DCH_to_char().

1956 {
1957  return asc_toupper(buff, strlen(buff));
1958 }
char * asc_toupper(const char *buff, size_t nbytes)
Definition: formatting.c:1877
static text* datetime_to_char_body ( TmToChar tmtc,
text fmt,
bool  is_interval,
Oid  collid 
)
static

Definition at line 3321 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, NULL, palloc(), parse_format(), pfree(), text_to_cstring(), and TRUE.

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

3322 {
3323  FormatNode *format;
3324  char *fmt_str,
3325  *result;
3326  bool incache;
3327  int fmt_len;
3328  text *res;
3329 
3330  /*
3331  * Convert fmt to C string
3332  */
3333  fmt_str = text_to_cstring(fmt);
3334  fmt_len = strlen(fmt_str);
3335 
3336  /*
3337  * Allocate workspace for result as C string
3338  */
3339  result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
3340  *result = '\0';
3341 
3342  if (fmt_len > DCH_CACHE_SIZE)
3343  {
3344  /*
3345  * Allocate new memory if format picture is bigger than static cache
3346  * and do not use cache (call parser always)
3347  */
3348  incache = FALSE;
3349 
3350  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3351 
3352  parse_format(format, fmt_str, DCH_keywords,
3354  }
3355  else
3356  {
3357  /*
3358  * Use cache buffers
3359  */
3360  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3361 
3362  incache = TRUE;
3363  format = ent->format;
3364  }
3365 
3366  /* The real work is here */
3367  DCH_to_char(format, is_interval, tmtc, result, collid);
3368 
3369  if (!incache)
3370  pfree(format);
3371 
3372  pfree(fmt_str);
3373 
3374  /* convert C-string result to TEXT format */
3375  res = cstring_to_text(result);
3376 
3377  pfree(result);
3378  return res;
3379 }
struct FormatNode FormatNode
Definition: formatting.c:150
static const KeySuffix DCH_suff[]
Definition: formatting.c:527
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:869
void pfree(void *pointer)
Definition: mcxt.c:992
#define DCH_CACHE_SIZE
Definition: formatting.c:370
#define FALSE
Definition: c.h:218
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:1223
static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
Definition: formatting.c:2355
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:375
static DCHCacheEntry * DCH_cache_fetch(const char *str)
Definition: formatting.c:3294
#define DCH_TYPE
Definition: formatting.c:99
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define NULL
Definition: c.h:226
char * text_to_cstring(const text *t)
Definition: varlena.c:184
void * palloc(Size size)
Definition: mcxt.c:891
static const KeyWord DCH_keywords[]
Definition: formatting.c:715
Definition: c.h:435
#define TRUE
Definition: c.h:214
static char format
Definition: pg_basebackup.c:83
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:113
static DCHCacheEntry * DCH_cache_fetch ( const char *  str)
static

Definition at line 3294 of file formatting.c.

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

Referenced by datetime_to_char_body(), and do_to_timestamp().

3295 {
3296  DCHCacheEntry *ent;
3297 
3298  if ((ent = DCH_cache_search(str)) == NULL)
3299  {
3300  /*
3301  * Not in the cache, must run parser and save a new format-picture to
3302  * the cache. Do not mark the cache entry valid until parsing
3303  * succeeds.
3304  */
3305  ent = DCH_cache_getnew(str);
3306 
3307  parse_format(ent->format, str, DCH_keywords,
3309 
3310  ent->valid = true;
3311  }
3312  return ent;
3313 }
static DCHCacheEntry * DCH_cache_getnew(const char *str)
Definition: formatting.c:3204
static const KeySuffix DCH_suff[]
Definition: formatting.c:527
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:869
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:1223
static DCHCacheEntry * DCH_cache_search(const char *str)
Definition: formatting.c:3266
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:375
#define DCH_TYPE
Definition: formatting.c:99
#define NULL
Definition: c.h:226
static const KeyWord DCH_keywords[]
Definition: formatting.c:715
static DCHCacheEntry * DCH_cache_getnew ( const char *  str)
static

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

3205 {
3206  DCHCacheEntry *ent;
3207 
3208  /* counter overflow check - paranoia? */
3209  if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3210  {
3211  DCHCounter = 0;
3212 
3213  for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3214  ent->age = (++DCHCounter);
3215  }
3216 
3217  /*
3218  * If cache is full, remove oldest entry (or recycle first not-valid one)
3219  */
3221  {
3222  DCHCacheEntry *old = DCHCache + 0;
3223 
3224 #ifdef DEBUG_TO_FROM_CHAR
3225  elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3226 #endif
3227  if (old->valid)
3228  {
3229  for (ent = DCHCache + 1; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3230  {
3231  if (!ent->valid)
3232  {
3233  old = ent;
3234  break;
3235  }
3236  if (ent->age < old->age)
3237  old = ent;
3238  }
3239  }
3240 #ifdef DEBUG_TO_FROM_CHAR
3241  elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3242 #endif
3243  old->valid = false;
3244  StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
3245  old->age = (++DCHCounter);
3246  /* caller is expected to fill format, then set valid */
3247  return old;
3248  }
3249  else
3250  {
3251 #ifdef DEBUG_TO_FROM_CHAR
3252  elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3253 #endif
3254  ent = DCHCache + n_DCHCache;
3255  ent->valid = false;
3256  StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
3257  ent->age = (++DCHCounter);
3258  /* caller is expected to fill format, then set valid */
3259  ++n_DCHCache;
3260  return ent;
3261  }
3262 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:376
#define DCH_CACHE_SIZE
Definition: formatting.c:370
static int n_DCHCache
Definition: formatting.c:392
#define DCH_CACHE_ENTRIES
Definition: formatting.c:371
static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:391
#define StrNCpy(dst, src, len)
Definition: c.h:826
#define elog
Definition: elog.h:219
static int DCHCounter
Definition: formatting.c:393
static DCHCacheEntry * DCH_cache_search ( const char *  str)
static

Definition at line 3266 of file formatting.c.

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

Referenced by DCH_cache_fetch().

3267 {
3268  int i;
3269  DCHCacheEntry *ent;
3270 
3271  /* counter overflow check - paranoia? */
3272  if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3273  {
3274  DCHCounter = 0;
3275 
3276  for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3277  ent->age = (++DCHCounter);
3278  }
3279 
3280  for (i = 0, ent = DCHCache; i < n_DCHCache; i++, ent++)
3281  {
3282  if (ent->valid && strcmp(ent->str, str) == 0)
3283  {
3284  ent->age = (++DCHCounter);
3285  return ent;
3286  }
3287  }
3288 
3289  return NULL;
3290 }
char str[DCH_CACHE_SIZE+1]
Definition: formatting.c:376
static int n_DCHCache
Definition: formatting.c:392
#define DCH_CACHE_ENTRIES
Definition: formatting.c:371
#define NULL
Definition: c.h:226
static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES]
Definition: formatting.c:391
int i
static int DCHCounter
Definition: formatting.c:393
static void DCH_from_char ( FormatNode node,
char *  in,
TmFromChar out 
)
static

Definition at line 2932 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, NULL, 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().

2933 {
2934  FormatNode *n;
2935  char *s;
2936  int len,
2937  value;
2938  bool fx_mode = false;
2939 
2940  for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
2941  {
2942  if (n->type != NODE_TYPE_ACTION)
2943  {
2944  /*
2945  * Separator, so consume one character from input string. Notice
2946  * we don't insist that the consumed character match the format's
2947  * character.
2948  */
2949  s++;
2950  continue;
2951  }
2952 
2953  /* Ignore spaces before fields when not in FX (fixed width) mode */
2954  if (!fx_mode && n->key->id != DCH_FX)
2955  {
2956  while (*s != '\0' && isspace((unsigned char) *s))
2957  s++;
2958  }
2959 
2960  from_char_set_mode(out, n->key->date_mode);
2961 
2962  switch (n->key->id)
2963  {
2964  case DCH_FX:
2965  fx_mode = true;
2966  break;
2967  case DCH_A_M:
2968  case DCH_P_M:
2969  case DCH_a_m:
2970  case DCH_p_m:
2972  ALL_UPPER, n->key->len, n);
2973  from_char_set_int(&out->pm, value % 2, n);
2974  out->clock = CLOCK_12_HOUR;
2975  break;
2976  case DCH_AM:
2977  case DCH_PM:
2978  case DCH_am:
2979  case DCH_pm:
2980  from_char_seq_search(&value, &s, ampm_strings,
2981  ALL_UPPER, n->key->len, n);
2982  from_char_set_int(&out->pm, value % 2, n);
2983  out->clock = CLOCK_12_HOUR;
2984  break;
2985  case DCH_HH:
2986  case DCH_HH12:
2987  from_char_parse_int_len(&out->hh, &s, 2, n);
2988  out->clock = CLOCK_12_HOUR;
2989  SKIP_THth(s, n->suffix);
2990  break;
2991  case DCH_HH24:
2992  from_char_parse_int_len(&out->hh, &s, 2, n);
2993  SKIP_THth(s, n->suffix);
2994  break;
2995  case DCH_MI:
2996  from_char_parse_int(&out->mi, &s, n);
2997  SKIP_THth(s, n->suffix);
2998  break;
2999  case DCH_SS:
3000  from_char_parse_int(&out->ss, &s, n);
3001  SKIP_THth(s, n->suffix);
3002  break;
3003  case DCH_MS: /* millisecond */
3004  len = from_char_parse_int_len(&out->ms, &s, 3, n);
3005 
3006  /*
3007  * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
3008  */
3009  out->ms *= len == 1 ? 100 :
3010  len == 2 ? 10 : 1;
3011 
3012  SKIP_THth(s, n->suffix);
3013  break;
3014  case DCH_US: /* microsecond */
3015  len = from_char_parse_int_len(&out->us, &s, 6, n);
3016 
3017  out->us *= len == 1 ? 100000 :
3018  len == 2 ? 10000 :
3019  len == 3 ? 1000 :
3020  len == 4 ? 100 :
3021  len == 5 ? 10 : 1;
3022 
3023  SKIP_THth(s, n->suffix);
3024  break;
3025  case DCH_SSSS:
3026  from_char_parse_int(&out->ssss, &s, n);
3027  SKIP_THth(s, n->suffix);
3028  break;
3029  case DCH_tz:
3030  case DCH_TZ:
3031  case DCH_OF:
3032  ereport(ERROR,
3033  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3034  errmsg("formatting field \"%s\" is only supported in to_char",
3035  n->key->name)));
3036  break;
3037  case DCH_A_D:
3038  case DCH_B_C:
3039  case DCH_a_d:
3040  case DCH_b_c:
3042  ALL_UPPER, n->key->len, n);
3043  from_char_set_int(&out->bc, value % 2, n);
3044  break;
3045  case DCH_AD:
3046  case DCH_BC:
3047  case DCH_ad:
3048  case DCH_bc:
3049  from_char_seq_search(&value, &s, adbc_strings,
3050  ALL_UPPER, n->key->len, n);
3051  from_char_set_int(&out->bc, value % 2, n);
3052  break;
3053  case DCH_MONTH:
3054  case DCH_Month:
3055  case DCH_month:
3057  MAX_MONTH_LEN, n);
3058  from_char_set_int(&out->mm, value + 1, n);
3059  break;
3060  case DCH_MON:
3061  case DCH_Mon:
3062  case DCH_mon:
3063  from_char_seq_search(&value, &s, months, ONE_UPPER,
3064  MAX_MON_LEN, n);
3065  from_char_set_int(&out->mm, value + 1, n);
3066  break;
3067  case DCH_MM:
3068  from_char_parse_int(&out->mm, &s, n);
3069  SKIP_THth(s, n->suffix);
3070  break;
3071  case DCH_DAY:
3072  case DCH_Day:
3073  case DCH_day:
3074  from_char_seq_search(&value, &s, days, ONE_UPPER,
3075  MAX_DAY_LEN, n);
3076  from_char_set_int(&out->d, value, n);
3077  out->d++;
3078  break;
3079  case DCH_DY:
3080  case DCH_Dy:
3081  case DCH_dy:
3082  from_char_seq_search(&value, &s, days, ONE_UPPER,
3083  MAX_DY_LEN, n);
3084  from_char_set_int(&out->d, value, n);
3085  out->d++;
3086  break;
3087  case DCH_DDD:
3088  from_char_parse_int(&out->ddd, &s, n);
3089  SKIP_THth(s, n->suffix);
3090  break;
3091  case DCH_IDDD:
3092  from_char_parse_int_len(&out->ddd, &s, 3, n);
3093  SKIP_THth(s, n->suffix);
3094  break;
3095  case DCH_DD:
3096  from_char_parse_int(&out->dd, &s, n);
3097  SKIP_THth(s, n->suffix);
3098  break;
3099  case DCH_D:
3100  from_char_parse_int(&out->d, &s, n);
3101  SKIP_THth(s, n->suffix);
3102  break;
3103  case DCH_ID:
3104  from_char_parse_int_len(&out->d, &s, 1, n);
3105  /* Shift numbering to match Gregorian where Sunday = 1 */
3106  if (++out->d > 7)
3107  out->d = 1;
3108  SKIP_THth(s, n->suffix);
3109  break;
3110  case DCH_WW:
3111  case DCH_IW:
3112  from_char_parse_int(&out->ww, &s, n);
3113  SKIP_THth(s, n->suffix);
3114  break;
3115  case DCH_Q:
3116 
3117  /*
3118  * We ignore 'Q' when converting to date because it is unclear
3119  * which date in the quarter to use, and some people specify
3120  * both quarter and month, so if it was honored it might
3121  * conflict with the supplied month. That is also why we don't
3122  * throw an error.
3123  *
3124  * We still parse the source string for an integer, but it
3125  * isn't stored anywhere in 'out'.
3126  */
3127  from_char_parse_int((int *) NULL, &s, n);
3128  SKIP_THth(s, n->suffix);
3129  break;
3130  case DCH_CC:
3131  from_char_parse_int(&out->cc, &s, n);
3132  SKIP_THth(s, n->suffix);
3133  break;
3134  case DCH_Y_YYY:
3135  {
3136  int matched,
3137  years,
3138  millennia,
3139  nch;
3140 
3141  matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3142  if (matched < 2)
3143  ereport(ERROR,
3144  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3145  errmsg("invalid input string for \"Y,YYY\"")));
3146  years += (millennia * 1000);
3147  from_char_set_int(&out->year, years, n);
3148  out->yysz = 4;
3149  s += nch;
3150  SKIP_THth(s, n->suffix);
3151  }
3152  break;
3153  case DCH_YYYY:
3154  case DCH_IYYY:
3155  from_char_parse_int(&out->year, &s, n);
3156  out->yysz = 4;
3157  SKIP_THth(s, n->suffix);
3158  break;
3159  case DCH_YYY:
3160  case DCH_IYY:
3161  if (from_char_parse_int(&out->year, &s, n) < 4)
3162  out->year = adjust_partial_year_to_2020(out->year);
3163  out->yysz = 3;
3164  SKIP_THth(s, n->suffix);
3165  break;
3166  case DCH_YY:
3167  case DCH_IY:
3168  if (from_char_parse_int(&out->year, &s, n) < 4)
3169  out->year = adjust_partial_year_to_2020(out->year);
3170  out->yysz = 2;
3171  SKIP_THth(s, n->suffix);
3172  break;
3173  case DCH_Y:
3174  case DCH_I:
3175  if (from_char_parse_int(&out->year, &s, n) < 4)
3176  out->year = adjust_partial_year_to_2020(out->year);
3177  out->yysz = 1;
3178  SKIP_THth(s, n->suffix);
3179  break;
3180  case DCH_RM:
3182  ALL_UPPER, MAX_RM_LEN, n);
3183  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
3184  break;
3185  case DCH_rm:
3187  ALL_LOWER, MAX_RM_LEN, n);
3188  from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
3189  break;
3190  case DCH_W:
3191  from_char_parse_int(&out->w, &s, n);
3192  SKIP_THth(s, n->suffix);
3193  break;
3194  case DCH_J:
3195  from_char_parse_int(&out->j, &s, n);
3196  SKIP_THth(s, n->suffix);
3197  break;
3198  }
3199  }
3200 }
static struct @76 value
#define NODE_TYPE_END
Definition: formatting.c:169
const KeyWord * key
Definition: formatting.c:164
static const char *const adbc_strings_long[]
Definition: formatting.c:223
static void from_char_set_int(int *dest, const int value, const FormatNode *node)
Definition: formatting.c:2114
FromCharDateMode date_mode
Definition: formatting.c:158
#define MAX_DY_LEN
Definition: formatting.c:292
int errcode(int sqlerrcode)
Definition: elog.c:575
static const char *const rm_months_upper[]
Definition: formatting.c:258
int id
Definition: formatting.c:156
static const char *const ampm_strings_long[]
Definition: formatting.c:250
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node)
Definition: formatting.c:2147
static const char *const adbc_strings[]
Definition: formatting.c:222
#define MONTHS_PER_YEAR
Definition: timestamp.h:81
#define MAX_MON_LEN
Definition: formatting.c:290
#define ONE_UPPER
Definition: formatting.c:283
const char *const months[]
Definition: datetime.c:71
#define NODE_TYPE_ACTION
Definition: formatting.c:170
#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:2325
#define SKIP_THth(ptr, _suf)
Definition: formatting.c:1969
const char *const days[]
Definition: datetime.c:74
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAX_RM_LEN
Definition: formatting.c:293
#define CLOCK_12_HOUR
Definition: formatting.c:177
static const char *const ampm_strings[]
Definition: formatting.c:249
const char * name
Definition: formatting.c:154
static const char *const months_full[]
Definition: formatting.c:184
int len
Definition: formatting.c:155
#define ALL_UPPER
Definition: formatting.c:284
static int adjust_partial_year_to_2020(int year)
Definition: formatting.c:2049
#define NULL
Definition: c.h:226
#define MAX_MONTH_LEN
Definition: formatting.c:289
static int from_char_parse_int(int *dest, char **src, FormatNode *node)
Definition: formatting.c:2237
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode)
Definition: formatting.c:2092
#define ALL_LOWER
Definition: formatting.c:285
#define MAX_DAY_LEN
Definition: formatting.c:291
static const char *const rm_months_lower[]
Definition: formatting.c:261
static void DCH_to_char ( FormatNode node,
bool  is_interval,
TmToChar in,
char *  out,
Oid  collid 
)
static

Definition at line 2355 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, INT64CONST, 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().

2356 {
2357  FormatNode *n;
2358  char *s;
2359  struct pg_tm *tm = &in->tm;
2360  int i;
2361 
2362  /* cache localized days and months */
2364 
2365  s = out;
2366  for (n = node; n->type != NODE_TYPE_END; n++)
2367  {
2368  if (n->type != NODE_TYPE_ACTION)
2369  {
2370  *s = n->character;
2371  s++;
2372  continue;
2373  }
2374 
2375  switch (n->key->id)
2376  {
2377  case DCH_A_M:
2378  case DCH_P_M:
2379  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2380  ? P_M_STR : A_M_STR);
2381  s += strlen(s);
2382  break;
2383  case DCH_AM:
2384  case DCH_PM:
2385  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2386  ? PM_STR : AM_STR);
2387  s += strlen(s);
2388  break;
2389  case DCH_a_m:
2390  case DCH_p_m:
2391  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2392  ? p_m_STR : a_m_STR);
2393  s += strlen(s);
2394  break;
2395  case DCH_am:
2396  case DCH_pm:
2397  strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2398  ? pm_STR : am_STR);
2399  s += strlen(s);
2400  break;
2401  case DCH_HH:
2402  case DCH_HH12:
2403 
2404  /*
2405  * display time as shown on a 12-hour clock, even for
2406  * intervals
2407  */
2408  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2409  tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? HOURS_PER_DAY / 2 :
2410  tm->tm_hour % (HOURS_PER_DAY / 2));
2411  if (S_THth(n->suffix))
2412  str_numth(s, s, S_TH_TYPE(n->suffix));
2413  s += strlen(s);
2414  break;
2415  case DCH_HH24:
2416  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2417  tm->tm_hour);
2418  if (S_THth(n->suffix))
2419  str_numth(s, s, S_TH_TYPE(n->suffix));
2420  s += strlen(s);
2421  break;
2422  case DCH_MI:
2423  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2424  tm->tm_min);
2425  if (S_THth(n->suffix))
2426  str_numth(s, s, S_TH_TYPE(n->suffix));
2427  s += strlen(s);
2428  break;
2429  case DCH_SS:
2430  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2431  tm->tm_sec);
2432  if (S_THth(n->suffix))
2433  str_numth(s, s, S_TH_TYPE(n->suffix));
2434  s += strlen(s);
2435  break;
2436  case DCH_MS: /* millisecond */
2437 #ifdef HAVE_INT64_TIMESTAMP
2438  sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
2439 #else
2440  /* No rint() because we can't overflow and we might print US */
2441  sprintf(s, "%03d", (int) (in->fsec * 1000));
2442 #endif
2443  if (S_THth(n->suffix))
2444  str_numth(s, s, S_TH_TYPE(n->suffix));
2445  s += strlen(s);
2446  break;
2447  case DCH_US: /* microsecond */
2448 #ifdef HAVE_INT64_TIMESTAMP
2449  sprintf(s, "%06d", (int) in->fsec);
2450 #else
2451  /* don't use rint() because we can't overflow 1000 */
2452  sprintf(s, "%06d", (int) (in->fsec * 1000000));
2453 #endif
2454  if (S_THth(n->suffix))
2455  str_numth(s, s, S_TH_TYPE(n->suffix));
2456  s += strlen(s);
2457  break;
2458  case DCH_SSSS:
2459  sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2460  tm->tm_min * SECS_PER_MINUTE +
2461  tm->tm_sec);
2462  if (S_THth(n->suffix))
2463  str_numth(s, s, S_TH_TYPE(n->suffix));
2464  s += strlen(s);
2465  break;
2466  case DCH_tz:
2468  if (tmtcTzn(in))
2469  {
2470  /* We assume here that timezone names aren't localized */
2471  char *p = asc_tolower_z(tmtcTzn(in));
2472 
2473  strcpy(s, p);
2474  pfree(p);
2475  s += strlen(s);
2476  }
2477  break;
2478  case DCH_TZ:
2480  if (tmtcTzn(in))
2481  {
2482  strcpy(s, tmtcTzn(in));
2483  s += strlen(s);
2484  }
2485  break;
2486  case DCH_OF:
2488  sprintf(s, "%c%0*d",
2489  (tm->tm_gmtoff >= 0) ? '+' : '-',
2490  S_FM(n->suffix) ? 0 : 2,
2491  abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2492  s += strlen(s);
2493  if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2494  {
2495  sprintf(s, ":%02d",
2496  (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2497  s += strlen(s);
2498  }
2499  break;
2500  case DCH_A_D:
2501  case DCH_B_C:
2503  strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2504  s += strlen(s);
2505  break;
2506  case DCH_AD:
2507  case DCH_BC:
2509  strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2510  s += strlen(s);
2511  break;
2512  case DCH_a_d:
2513  case DCH_b_c:
2515  strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2516  s += strlen(s);
2517  break;
2518  case DCH_ad:
2519  case DCH_bc:
2521  strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2522  s += strlen(s);
2523  break;
2524  case DCH_MONTH:
2526  if (!tm->tm_mon)
2527  break;
2528  if (S_TM(n->suffix))
2529  {
2530  char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2531 
2532  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2533  strcpy(s, str);
2534  else
2535  ereport(ERROR,
2536  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2537  errmsg("localized string format value too long")));
2538  }
2539  else
2540  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2541  asc_toupper_z(months_full[tm->tm_mon - 1]));
2542  s += strlen(s);
2543  break;
2544  case DCH_Month:
2546  if (!tm->tm_mon)
2547  break;
2548  if (S_TM(n->suffix))
2549  {
2550  char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2551 
2552  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2553  strcpy(s, str);
2554  else
2555  ereport(ERROR,
2556  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2557  errmsg("localized string format value too long")));
2558  }
2559  else
2560  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2561  months_full[tm->tm_mon - 1]);
2562  s += strlen(s);
2563  break;
2564  case DCH_month:
2566  if (!tm->tm_mon)
2567  break;
2568  if (S_TM(n->suffix))
2569  {
2570  char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2571 
2572  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2573  strcpy(s, str);
2574  else
2575  ereport(ERROR,
2576  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2577  errmsg("localized string format value too long")));
2578  }
2579  else
2580  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2581  asc_tolower_z(months_full[tm->tm_mon - 1]));
2582  s += strlen(s);
2583  break;
2584  case DCH_MON:
2586  if (!tm->tm_mon)
2587  break;
2588  if (S_TM(n->suffix))
2589  {
2590  char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2591 
2592  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2593  strcpy(s, str);
2594  else
2595  ereport(ERROR,
2596  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2597  errmsg("localized string format value too long")));
2598  }
2599  else
2600  strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2601  s += strlen(s);
2602  break;
2603  case DCH_Mon:
2605  if (!tm->tm_mon)
2606  break;
2607  if (S_TM(n->suffix))
2608  {
2609  char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2610 
2611  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2612  strcpy(s, str);
2613  else
2614  ereport(ERROR,
2615  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2616  errmsg("localized string format value too long")));
2617  }
2618  else
2619  strcpy(s, months[tm->tm_mon - 1]);
2620  s += strlen(s);
2621  break;
2622  case DCH_mon:
2624  if (!tm->tm_mon)
2625  break;
2626  if (S_TM(n->suffix))
2627  {
2628  char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2629 
2630  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2631  strcpy(s, str);
2632  else
2633  ereport(ERROR,
2634  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2635  errmsg("localized string format value too long")));
2636  }
2637  else
2638  strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2639  s += strlen(s);
2640  break;
2641  case DCH_MM:
2642  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2643  tm->tm_mon);
2644  if (S_THth(n->suffix))
2645  str_numth(s, s, S_TH_TYPE(n->suffix));
2646  s += strlen(s);
2647  break;
2648  case DCH_DAY:
2650  if (S_TM(n->suffix))
2651  {
2652  char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2653 
2654  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2655  strcpy(s, str);
2656  else
2657  ereport(ERROR,
2658  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2659  errmsg("localized string format value too long")));
2660  }
2661  else
2662  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2663  asc_toupper_z(days[tm->tm_wday]));
2664  s += strlen(s);
2665  break;
2666  case DCH_Day:
2668  if (S_TM(n->suffix))
2669  {
2670  char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2671 
2672  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2673  strcpy(s, str);
2674  else
2675  ereport(ERROR,
2676  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2677  errmsg("localized string format value too long")));
2678  }
2679  else
2680  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2681  days[tm->tm_wday]);
2682  s += strlen(s);
2683  break;
2684  case DCH_day:
2686  if (S_TM(n->suffix))
2687  {
2688  char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
2689 
2690  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2691  strcpy(s, str);
2692  else
2693  ereport(ERROR,
2694  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2695  errmsg("localized string format value too long")));
2696  }
2697  else
2698  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2699  asc_tolower_z(days[tm->tm_wday]));
2700  s += strlen(s);
2701  break;
2702  case DCH_DY:
2704  if (S_TM(n->suffix))
2705  {
2706  char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
2707 
2708  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2709  strcpy(s, str);
2710  else
2711  ereport(ERROR,
2712  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2713  errmsg("localized string format value too long")));
2714  }
2715  else
2716  strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
2717  s += strlen(s);
2718  break;
2719  case DCH_Dy:
2721  if (S_TM(n->suffix))
2722  {
2723  char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
2724 
2725  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2726  strcpy(s, str);
2727  else
2728  ereport(ERROR,
2729  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2730  errmsg("localized string format value too long")));
2731  }
2732  else
2733  strcpy(s, days_short[tm->tm_wday]);
2734  s += strlen(s);
2735  break;
2736  case DCH_dy:
2738  if (S_TM(n->suffix))
2739  {
2740  char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
2741 
2742  if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2743  strcpy(s, str);
2744  else
2745  ereport(ERROR,
2746  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2747  errmsg("localized string format value too long")));
2748  }
2749  else
2750  strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
2751  s += strlen(s);
2752  break;
2753  case DCH_DDD:
2754  case DCH_IDDD:
2755  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
2756  (n->key->id == DCH_DDD) ?
2757  tm->tm_yday :
2758  date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
2759  if (S_THth(n->suffix))
2760  str_numth(s, s, S_TH_TYPE(n->suffix));
2761  s += strlen(s);
2762  break;
2763  case DCH_DD:
2764  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
2765  if (S_THth(n->suffix))
2766  str_numth(s, s, S_TH_TYPE(n->suffix));
2767  s += strlen(s);
2768  break;
2769  case DCH_D:
2771  sprintf(s, "%d", tm->tm_wday + 1);
2772  if (S_THth(n->suffix))
2773  str_numth(s, s, S_TH_TYPE(n->suffix));
2774  s += strlen(s);
2775  break;
2776  case DCH_ID:
2778  sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
2779  if (S_THth(n->suffix))
2780  str_numth(s, s, S_TH_TYPE(n->suffix));
2781  s += strlen(s);
2782  break;
2783  case DCH_WW:
2784  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2785  (tm->tm_yday - 1) / 7 + 1);
2786  if (S_THth(n->suffix))
2787  str_numth(s, s, S_TH_TYPE(n->suffix));
2788  s += strlen(s);
2789  break;
2790  case DCH_IW:
2791  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2792  date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
2793  if (S_THth(n->suffix))
2794  str_numth(s, s, S_TH_TYPE(n->suffix));
2795  s += strlen(s);
2796  break;
2797  case DCH_Q:
2798  if (!tm->tm_mon)
2799  break;
2800  sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
2801  if (S_THth(n->suffix))
2802  str_numth(s, s, S_TH_TYPE(n->suffix));
2803  s += strlen(s);
2804  break;
2805  case DCH_CC:
2806  if (is_interval) /* straight calculation */
2807  i = tm->tm_year / 100;
2808  else
2809  {
2810  if (tm->tm_year > 0)
2811  /* Century 20 == 1901 - 2000 */
2812  i = (tm->tm_year - 1) / 100 + 1;
2813  else
2814  /* Century 6BC == 600BC - 501BC */
2815  i = tm->tm_year / 100 - 1;
2816  }
2817  if (i <= 99 && i >= -99)
2818  sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
2819  else
2820  sprintf(s, "%d", i);
2821  if (S_THth(n->suffix))
2822  str_numth(s, s, S_TH_TYPE(n->suffix));
2823  s += strlen(s);
2824  break;
2825  case DCH_Y_YYY:
2826  i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
2827  sprintf(s, "%d,%03d", i,
2828  ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
2829  if (S_THth(n->suffix))
2830  str_numth(s, s, S_TH_TYPE(n->suffix));
2831  s += strlen(s);
2832  break;
2833  case DCH_YYYY:
2834  case DCH_IYYY:
2835  sprintf(s, "%0*d",
2836  S_FM(n->suffix) ? 0 :
2837  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
2838  (n->key->id == DCH_YYYY ?
2839  ADJUST_YEAR(tm->tm_year, is_interval) :
2841  tm->tm_mon,
2842  tm->tm_mday),
2843  is_interval)));
2844  if (S_THth(n->suffix))
2845  str_numth(s, s, S_TH_TYPE(n->suffix));
2846  s += strlen(s);
2847  break;
2848  case DCH_YYY:
2849  case DCH_IYY:
2850  sprintf(s, "%0*d",
2851  S_FM(n->suffix) ? 0 :
2852  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
2853  (n->key->id == DCH_YYY ?
2854  ADJUST_YEAR(tm->tm_year, is_interval) :
2856  tm->tm_mon,
2857  tm->tm_mday),
2858  is_interval)) % 1000);
2859  if (S_THth(n->suffix))
2860  str_numth(s, s, S_TH_TYPE(n->suffix));
2861  s += strlen(s);
2862  break;
2863  case DCH_YY:
2864  case DCH_IY:
2865  sprintf(s, "%0*d",
2866  S_FM(n->suffix) ? 0 :
2867  (ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
2868  (n->key->id == DCH_YY ?
2869  ADJUST_YEAR(tm->tm_year, is_interval) :
2871  tm->tm_mon,
2872  tm->tm_mday),
2873  is_interval)) % 100);
2874  if (S_THth(n->suffix))
2875  str_numth(s, s, S_TH_TYPE(n->suffix));
2876  s += strlen(s);
2877  break;
2878  case DCH_Y:
2879  case DCH_I:
2880  sprintf(s, "%1d",
2881  (n->key->id == DCH_Y ?
2882  ADJUST_YEAR(tm->tm_year, is_interval) :
2884  tm->tm_mon,
2885  tm->tm_mday),
2886  is_interval)) % 10);
2887  if (S_THth(n->suffix))
2888  str_numth(s, s, S_TH_TYPE(n->suffix));
2889  s += strlen(s);
2890  break;
2891  case DCH_RM:
2892  if (!tm->tm_mon)
2893  break;
2894  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2896  s += strlen(s);
2897  break;
2898  case DCH_rm:
2899  if (!tm->tm_mon)
2900  break;
2901  sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2903  s += strlen(s);
2904  break;
2905  case DCH_W:
2906  sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
2907  if (S_THth(n->suffix))
2908  str_numth(s, s, S_TH_TYPE(n->suffix));
2909  s += strlen(s);
2910  break;
2911  case DCH_J:
2912  sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
2913  if (S_THth(n->suffix))
2914  str_numth(s, s, S_TH_TYPE(n->suffix));
2915  s += strlen(s);
2916  break;
2917  }
2918  }
2919 
2920  *s = '\0';
2921 }
#define a_m_STR
Definition: formatting.c:230
#define NODE_TYPE_END
Definition: formatting.c:169
const KeyWord * key
Definition: formatting.c:164
int tm_wday
Definition: pgtime.h:33
#define b_c_STR
Definition: formatting.c:208
#define S_THth(_s)
Definition: formatting.c:511
int tm_hour
Definition: pgtime.h:29
#define BC_STR
Definition: formatting.c:209
#define A_M_STR
Definition: formatting.c:229
static char * str_initcap_z(const char *buff, Oid collid)
Definition: formatting.c:1943
fsec_t fsec
Definition: formatting.c:458
static char * asc_tolower_z(const char *buff)
Definition: formatting.c:1949
#define AD_STR
Definition: formatting.c:204
int errcode(int sqlerrcode)
Definition: elog.c:575
struct pg_tm tm
Definition: formatting.c:457
#define p_m_STR
Definition: formatting.c:235
#define am_STR
Definition: formatting.c:232
static char * str_tolower_z(const char *buff, Oid collid)
Definition: formatting.c:1931
long int tm_gmtoff
Definition: pgtime.h:36
Definition: pgtime.h:25
char * localized_abbrev_months[12]
Definition: pg_locale.c:91
static char * str_numth(char *dest, char *num, int type)
Definition: formatting.c:1434
static const char *const rm_months_upper[]
Definition: formatting.c:258
int id
Definition: formatting.c:156
#define pm_STR
Definition: formatting.c:237
static struct pg_tm tm
Definition: localtime.c:103
#define MONTHS_PER_YEAR
Definition: timestamp.h:81
void pfree(void *pointer)
Definition: mcxt.c:992
const char *const months[]
Definition: datetime.c:71
#define NODE_TYPE_ACTION
Definition: formatting.c:170
#define ERROR
Definition: elog.h:43
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:4433
#define S_FM(_s)
Definition: formatting.c:517
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:4487
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:90
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:100
char character
Definition: formatting.c:165
const char *const days[]
Definition: datetime.c:74
#define A_D_STR
Definition: formatting.c:202
#define a_d_STR
Definition: formatting.c:203
#define ereport(elevel, rest)
Definition: elog.h:122
#define SECS_PER_HOUR
Definition: timestamp.h:99
#define bc_STR
Definition: formatting.c:210
#define S_TH_TYPE(_s)
Definition: formatting.c:514
static const char *const months_full[]
Definition: formatting.c:184
int len
Definition: formatting.c:155
char * localized_full_days[7]
Definition: pg_locale.c:90
int date2j(int y, int m, int d)
Definition: datetime.c:297
#define ad_STR
Definition: formatting.c:205
void cache_locale_time(void)
Definition: pg_locale.c:781
#define INT64CONST(x)
Definition: c.h:307
#define P_M_STR
Definition: formatting.c:234
static char * asc_toupper_z(const char *buff)
Definition: formatting.c:1955
#define ADJUST_YEAR(year, is_interval)
Definition: formatting.c:200
#define tmtcTzn(_X)
Definition: formatting.c:463
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:1937
#define INVALID_FOR_INTERVAL
Definition: formatting.c:484
int date2isoyearday(int year, int mon, int mday)
Definition: timestamp.c:4544
int i
#define S_TM(_s)
Definition: formatting.c:519
int tm_yday
Definition: pgtime.h:34
#define PM_STR
Definition: formatting.c:236
#define AM_STR
Definition: formatting.c:231
#define TM_SUFFIX_LEN
Definition: formatting.c:525
int tm_sec
Definition: pgtime.h:27
char * localized_full_months[12]
Definition: pg_locale.c:92
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:113
char * localized_abbrev_days[7]
Definition: pg_locale.c:89
int tm_min
Definition: pgtime.h:28
static const char *const rm_months_lower[]
Definition: formatting.c:261
static const char *const days_short[]
Definition: formatting.c:189
#define B_C_STR
Definition: formatting.c:207
static void do_to_timestamp ( text date_txt,
text fmt,
struct pg_tm tm,
fsec_t fsec 
)
static

Definition at line 3562 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, HAVE_INT64_TIMESTAMP, TmFromChar::hh, HOURS_PER_DAY, i, INT64CONST, isleap, isoweek2date(), isoweek2j(), isoweekdate2date(), TmFromChar::j, j2date(), TmFromChar::mi, MINS_PER_HOUR, TmFromChar::mm, TmFromChar::mode, MONTH, MONTHS_PER_YEAR, TmFromChar::ms, NULL, 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().

3564 {
3565  FormatNode *format;
3566  TmFromChar tmfc;
3567  int fmt_len;
3568  char *date_str;
3569  int fmask;
3570 
3571  date_str = text_to_cstring(date_txt);
3572 
3573  ZERO_tmfc(&tmfc);
3574  ZERO_tm(tm);
3575  *fsec = 0;
3576  fmask = 0; /* bit mask for ValidateDate() */
3577 
3578  fmt_len = VARSIZE_ANY_EXHDR(fmt);
3579 
3580  if (fmt_len)
3581  {
3582  char *fmt_str;
3583  bool incache;
3584 
3585  fmt_str = text_to_cstring(fmt);
3586 
3587  if (fmt_len > DCH_CACHE_SIZE)
3588  {
3589  /*
3590  * Allocate new memory if format picture is bigger than static
3591  * cache and do not use cache (call parser always)
3592  */
3593  incache = FALSE;
3594 
3595  format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3596 
3597  parse_format(format, fmt_str, DCH_keywords,
3599  }
3600  else
3601  {
3602  /*
3603  * Use cache buffers
3604  */
3605  DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3606 
3607  incache = TRUE;
3608  format = ent->format;
3609  }
3610 
3611 #ifdef DEBUG_TO_FROM_CHAR
3612  /* dump_node(format, fmt_len); */
3613  /* dump_index(DCH_keywords, DCH_index); */
3614 #endif
3615 
3616  DCH_from_char(format, date_str, &tmfc);
3617 
3618  pfree(fmt_str);
3619  if (!incache)
3620  pfree(format);
3621  }
3622 
3623  DEBUG_TMFC(&tmfc);
3624 
3625  /*
3626  * Convert to_date/to_timestamp input fields to standard 'tm'
3627  */
3628  if (tmfc.ssss)
3629  {
3630  int x = tmfc.ssss;
3631 
3632  tm->tm_hour = x / SECS_PER_HOUR;
3633  x %= SECS_PER_HOUR;
3634  tm->tm_min = x / SECS_PER_MINUTE;
3635  x %= SECS_PER_MINUTE;
3636  tm->tm_sec = x;
3637  }
3638 
3639  if (tmfc.ss)
3640  tm->tm_sec = tmfc.ss;
3641  if (tmfc.mi)
3642  tm->tm_min = tmfc.mi;
3643  if (tmfc.hh)
3644  tm->tm_hour = tmfc.hh;
3645 
3646  if (tmfc.clock == CLOCK_12_HOUR)
3647  {
3648  if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
3649  ereport(ERROR,
3650  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3651  errmsg("hour \"%d\" is invalid for the 12-hour clock",
3652  tm->tm_hour),
3653  errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
3654 
3655  if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
3656  tm->tm_hour += HOURS_PER_DAY / 2;
3657  else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
3658  tm->tm_hour = 0;
3659  }
3660 
3661  if (tmfc.year)
3662  {
3663  /*
3664  * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
3665  * the year in the given century. Keep in mind that the 21st century
3666  * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
3667  * 600BC to 501BC.
3668  */
3669  if (tmfc.cc && tmfc.yysz <= 2)
3670  {
3671  if (tmfc.bc)
3672  tmfc.cc = -tmfc.cc;
3673  tm->tm_year = tmfc.year % 100;
3674  if (tm->tm_year)
3675  {
3676  if (tmfc.cc >= 0)
3677  tm->tm_year += (tmfc.cc - 1) * 100;
3678  else
3679  tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
3680  }
3681  else
3682  {
3683  /* find century year for dates ending in "00" */
3684  tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
3685  }
3686  }
3687  else
3688  {
3689  /* If a 4-digit year is provided, we use that and ignore CC. */
3690  tm->tm_year = tmfc.year;
3691  if (tmfc.bc && tm->tm_year > 0)
3692  tm->tm_year = -(tm->tm_year - 1);
3693  }
3694  fmask |= DTK_M(YEAR);
3695  }
3696  else if (tmfc.cc)
3697  {
3698  /* use first year of century */
3699  if (tmfc.bc)
3700  tmfc.cc = -tmfc.cc;
3701  if (tmfc.cc >= 0)
3702  /* +1 because 21st century started in 2001 */
3703  tm->tm_year = (tmfc.cc - 1) * 100 + 1;
3704  else
3705  /* +1 because year == 599 is 600 BC */
3706  tm->tm_year = tmfc.cc * 100 + 1;
3707  fmask |= DTK_M(YEAR);
3708  }
3709 
3710  if (tmfc.j)
3711  {
3712  j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3713  fmask |= DTK_DATE_M;
3714  }
3715 
3716  if (tmfc.ww)
3717  {
3718  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3719  {
3720  /*
3721  * If tmfc.d is not set, then the date is left at the beginning of
3722  * the ISO week (Monday).
3723  */
3724  if (tmfc.d)
3725  isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3726  else
3727  isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3728  fmask |= DTK_DATE_M;
3729  }
3730  else
3731  tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
3732  }
3733 
3734  if (tmfc.w)
3735  tmfc.dd = (tmfc.w - 1) * 7 + 1;
3736  if (tmfc.dd)
3737  {
3738  tm->tm_mday = tmfc.dd;
3739  fmask |= DTK_M(DAY);
3740  }
3741  if (tmfc.mm)
3742  {
3743  tm->tm_mon = tmfc.mm;
3744  fmask |= DTK_M(MONTH);
3745  }
3746 
3747  if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
3748  {
3749  /*
3750  * The month and day field have not been set, so we use the
3751  * day-of-year field to populate them. Depending on the date mode,
3752  * this field may be interpreted as a Gregorian day-of-year, or an ISO
3753  * week date day-of-year.
3754  */
3755 
3756  if (!tm->tm_year && !tmfc.bc)
3757  ereport(ERROR,
3758  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3759  errmsg("cannot calculate day of year without year information")));
3760 
3761  if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3762  {
3763  int j0; /* zeroth day of the ISO year, in Julian */
3764 
3765  j0 = isoweek2j(tm->tm_year, 1) - 1;
3766 
3767  j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3768  fmask |= DTK_DATE_M;
3769  }
3770  else
3771  {
3772  const int *y;
3773  int i;
3774 
3775  static const int ysum[2][13] = {
3776  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
3777  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
3778 
3779  y = ysum[isleap(tm->tm_year)];
3780 
3781  for (i = 1; i <= MONTHS_PER_YEAR; i++)
3782  {
3783  if (tmfc.ddd <= y[i])
3784  break;
3785  }
3786  if (tm->tm_mon <= 1)
3787  tm->tm_mon = i;
3788 
3789  if (tm->tm_mday <= 1)
3790  tm->tm_mday = tmfc.ddd - y[i - 1];
3791 
3792  fmask |= DTK_M(MONTH) | DTK_M(DAY);
3793  }
3794  }
3795 
3796 #ifdef HAVE_INT64_TIMESTAMP
3797  if (tmfc.ms)
3798  *fsec += tmfc.ms * 1000;
3799  if (tmfc.us)
3800  *fsec += tmfc.us;
3801 #else
3802  if (tmfc.ms)
3803  *fsec += (double) tmfc.ms / 1000;
3804  if (tmfc.us)
3805  *fsec += (double) tmfc.us / 1000000;
3806 #endif
3807 
3808  /* Range-check date fields according to bit mask computed above */
3809  if (fmask != 0)
3810  {
3811  /* We already dealt with AD/BC, so pass isjulian = true */
3812  int dterr = ValidateDate(fmask, true, false, false, tm);
3813 
3814  if (dterr != 0)
3815  {
3816  /*
3817  * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
3818  * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
3819  * irrelevant hint about datestyle.
3820  */
3821  DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3822  }
3823  }
3824 
3825  /* Range-check time fields too */
3826  if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
3827  tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
3828  tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
3829 #ifdef HAVE_INT64_TIMESTAMP
3830  *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC
3831 #else
3832  *fsec < 0 || *fsec >= 1
3833 #endif
3834  )
3835  DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3836 
3837  DEBUG_TM(tm);
3838 
3839  pfree(date_str);
3840 }
#define DEBUG_TM(_X)
Definition: formatting.c:448
struct FormatNode FormatNode
Definition: formatting.c:150
#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:3871
#define USECS_PER_SEC
Definition: timestamp.h:106
#define YEAR
Definition: datetime.h:93
int tm_hour
Definition: pgtime.h:29
#define isleap(y)
Definition: datetime.h:281
static const KeySuffix DCH_suff[]
Definition: formatting.c:527
static const int DCH_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:869
int errcode(int sqlerrcode)
Definition: elog.c:575
void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
Definition: timestamp.c:4415
static void DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
Definition: formatting.c:2932
FromCharDateMode mode
Definition: formatting.c:406
#define DTK_DATE_M
Definition: datetime.h:194
#define MINS_PER_HOUR
Definition: timestamp.h:101
#define MONTHS_PER_YEAR
Definition: timestamp.h:81
void pfree(void *pointer)
Definition: mcxt.c:992
#define DCH_CACHE_SIZE
Definition: formatting.c:370
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:291
#define FALSE
Definition: c.h:218
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:1223
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:90
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:100
FormatNode format[DCH_CACHE_SIZE+1]
Definition: formatting.c:375
static DCHCacheEntry * DCH_cache_fetch(const char *str)
Definition: formatting.c:3294
#define ereport(elevel, rest)
Definition: elog.h:122
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:322
#define SECS_PER_HOUR
Definition: timestamp.h:99
#define CLOCK_12_HOUR
Definition: formatting.c:177
#define MONTH
Definition: datetime.h:92
#define DCH_TYPE
Definition: formatting.c:99
void isoweek2date(int woy, int *year, int *mon, int *mday)
Definition: timestamp.c:4402
#define ZERO_tmfc(_X)
Definition: formatting.c:428
int isoweek2j(int year, int week)
Definition: timestamp.c:4382
#define NULL
Definition: c.h:226
#define INT64CONST(x)
Definition: c.h:307
#define DEBUG_TMFC(_X)
Definition: formatting.c:447
char * text_to_cstring(const text *t)
Definition: varlena.c:184
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
static const KeyWord DCH_keywords[]
Definition: formatting.c:715
int i
#define DTK_M(t)
Definition: datetime.h:190
#define TRUE
Definition: c.h:214
static char format
Definition: pg_basebackup.c:83
int tm_sec
Definition: pgtime.h:27
#define HAVE_INT64_TIMESTAMP
Definition: c.h:347
#define ZERO_tm(_X)
Definition: formatting.c:466
int tm_min
Definition: pgtime.h:28
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2558
static char * fill_str ( char *  str,
int  c,
int  max 
)
static

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

3850 {
3851  memset(str, c, max);
3852  *(str + max) = '\0';
3853  return str;
3854 }
char * c
Datum float4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5451 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_P, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, rint(), sign, snprintf(), val, and value.

5452 {
5454  text *fmt = PG_GETARG_TEXT_P(1);
5455  NUMDesc Num;
5456  FormatNode *format;
5457  text *result;
5458  bool shouldFree;
5459  int out_pre_spaces = 0,
5460  sign = 0;
5461  char *numstr,
5462  *orgnum,
5463  *p;
5464 
5466 
5467  if (IS_ROMAN(&Num))
5468  numstr = orgnum = int_to_roman((int) rint(value));
5469  else if (IS_EEEE(&Num))
5470  {
5471  numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5472  if (isnan(value) || is_infinite(value))
5473  {
5474  /*
5475  * Allow 6 characters for the leading sign, the decimal point,
5476  * "e", the exponent's sign and two exponent digits.
5477  */
5478  numstr = (char *) palloc(Num.pre + Num.post + 7);
5479  fill_str(numstr, '#', Num.pre + Num.post + 6);
5480  *numstr = ' ';
5481  *(numstr + Num.pre + 1) = '.';
5482  }
5483  else
5484  {
5485  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5486 
5487  /*
5488  * Swap a leading positive sign for a space.
5489  */
5490  if (*orgnum == '+')
5491  *orgnum = ' ';
5492 
5493  numstr = orgnum;
5494  }
5495  }
5496  else
5497  {
5498  float4 val = value;
5499  int numstr_pre_len;
5500 
5501  if (IS_MULTI(&Num))
5502  {
5503  float multi = pow((double) 10, (double) Num.multi);
5504 
5505  val = value * multi;
5506  Num.pre += Num.multi;
5507  }
5508 
5509  orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
5510  snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
5511  numstr_pre_len = strlen(orgnum);
5512 
5513  /* adjust post digits to fit max float digits */
5514  if (numstr_pre_len >= FLT_DIG)
5515  Num.post = 0;
5516  else if (numstr_pre_len + Num.post > FLT_DIG)
5517  Num.post = FLT_DIG - numstr_pre_len;
5518  snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
5519 
5520  if (*orgnum == '-')
5521  { /* < 0 */
5522  sign = '-';
5523  numstr = orgnum + 1;
5524  }
5525  else
5526  {
5527  sign = '+';
5528  numstr = orgnum;
5529  }
5530 
5531  if ((p = strchr(numstr, '.')))
5532  numstr_pre_len = p - numstr;
5533  else
5534  numstr_pre_len = strlen(numstr);
5535 
5536  /* needs padding? */
5537  if (numstr_pre_len < Num.pre)
5538  out_pre_spaces = Num.pre - numstr_pre_len;
5539  /* overflowed prefix digit format? */
5540  else if (numstr_pre_len > Num.pre)
5541  {
5542  numstr = (char *) palloc(Num.pre + Num.post + 2);
5543  fill_str(numstr, '#', Num.pre + Num.post + 1);
5544  *(numstr + Num.pre) = '.';
5545  }
5546  }
5547 
5549  PG_RETURN_TEXT_P(result);
5550 }
static struct @76 value
#define MAXDOUBLEWIDTH
Definition: formatting.c:121
#define IS_EEEE(_f)
Definition: formatting.c:353
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXFLOATWIDTH
Definition: formatting.c:120
#define NUM_TOCHAR_finish
Definition: formatting.c:5038
#define IS_ROMAN(_f)
Definition: formatting.c:351
#define NUM_TOCHAR_prepare
Definition: formatting.c:5025
#define IS_MULTI(_f)
Definition: formatting.c:352
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3849
static char * int_to_roman(int number)
Definition: formatting.c:4047
int pre
Definition: formatting.c:304
double rint(double x)
Definition: rint.c:22
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:236
float float4
Definition: c.h:377
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
int post
Definition: formatting.c:304
int is_infinite(double val)
Definition: float.c:199
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int multi
Definition: formatting.c:304
Definition: c.h:435
static char format
Definition: pg_basebackup.c:83
long val
Definition: informix.c:689
Datum float8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5557 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_P, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, rint(), sign, snprintf(), val, and value.

5558 {
5560  text *fmt = PG_GETARG_TEXT_P(1);
5561  NUMDesc Num;
5562  FormatNode *format;
5563  text *result;
5564  bool shouldFree;
5565  int out_pre_spaces = 0,
5566  sign = 0;
5567  char *numstr,
5568  *orgnum,
5569  *p;
5570 
5572 
5573  if (IS_ROMAN(&Num))
5574  numstr = orgnum = int_to_roman((int) rint(value));
5575  else if (IS_EEEE(&Num))
5576  {
5577  numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5578  if (isnan(value) || is_infinite(value))
5579  {
5580  /*
5581  * Allow 6 characters for the leading sign, the decimal point,
5582  * "e", the exponent's sign and two exponent digits.
5583  */
5584  numstr = (char *) palloc(Num.pre + Num.post + 7);
5585  fill_str(numstr, '#', Num.pre + Num.post + 6);
5586  *numstr = ' ';
5587  *(numstr + Num.pre + 1) = '.';
5588  }
5589  else
5590  {
5591  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5592 
5593  /*
5594  * Swap a leading positive sign for a space.
5595  */
5596  if (*orgnum == '+')
5597  *orgnum = ' ';
5598 
5599  numstr = orgnum;
5600  }
5601  }
5602  else
5603  {
5604  float8 val = value;
5605  int numstr_pre_len;
5606 
5607  if (IS_MULTI(&Num))
5608  {
5609  double multi = pow((double) 10, (double) Num.multi);
5610 
5611  val = value * multi;
5612  Num.pre += Num.multi;
5613  }
5614  orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5615  numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
5616 
5617  /* adjust post digits to fit max double digits */
5618  if (numstr_pre_len >= DBL_DIG)
5619  Num.post = 0;
5620  else if (numstr_pre_len + Num.post > DBL_DIG)
5621  Num.post = DBL_DIG - numstr_pre_len;
5622  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
5623 
5624  if (*orgnum == '-')
5625  { /* < 0 */
5626  sign = '-';
5627  numstr = orgnum + 1;
5628  }
5629  else
5630  {
5631  sign = '+';
5632  numstr = orgnum;
5633  }
5634 
5635  if ((p = strchr(numstr, '.')))
5636  numstr_pre_len = p - numstr;
5637  else
5638  numstr_pre_len = strlen(numstr);
5639 
5640  /* needs padding? */
5641  if (numstr_pre_len < Num.pre)
5642  out_pre_spaces = Num.pre - numstr_pre_len;
5643  /* overflowed prefix digit format? */
5644  else if (numstr_pre_len > Num.pre)
5645  {
5646  numstr = (char *) palloc(Num.pre + Num.post + 2);
5647  fill_str(numstr, '#', Num.pre + Num.post + 1);
5648  *(numstr + Num.pre) = '.';
5649  }
5650  }
5651 
5653  PG_RETURN_TEXT_P(result);
5654 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:237
static struct @76 value
#define MAXDOUBLEWIDTH
Definition: formatting.c:121
#define IS_EEEE(_f)
Definition: formatting.c:353
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define NUM_TOCHAR_finish
Definition: formatting.c:5038
#define IS_ROMAN(_f)
Definition: formatting.c:351
#define NUM_TOCHAR_prepare
Definition: formatting.c:5025
double float8
Definition: c.h:378
#define IS_MULTI(_f)
Definition: formatting.c:352
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3849
static char * int_to_roman(int number)
Definition: formatting.c:4047
int pre
Definition: formatting.c:304
double rint(double x)
Definition: rint.c:22
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
int post
Definition: formatting.c:304
int is_infinite(double val)
Definition: float.c:199
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int multi
Definition: formatting.c:304
Definition: c.h:435
static char format
Definition: pg_basebackup.c:83
long val
Definition: informix.c:689
static int from_char_parse_int ( int *  dest,
char **  src,
FormatNode node 
)
static

Definition at line 2237 of file formatting.c.

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

Referenced by DCH_from_char().

2238 {
2239  return from_char_parse_int_len(dest, src, node->key->len, node);
2240 }
const KeyWord * key
Definition: formatting.c:164
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node)
Definition: formatting.c:2147
int len
Definition: formatting.c:155
static int from_char_parse_int_len ( int *  dest,
char **  src,
const int  len,
FormatNode node 
)
static

Definition at line 2147 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, NULL, S_FM, strlcpy(), strspace_len(), and FormatNode::suffix.

Referenced by DCH_from_char(), and from_char_parse_int().

2148 {
2149  long result;
2150  char copy[DCH_MAX_ITEM_SIZ + 1];
2151  char *init = *src;
2152  int used;
2153 
2154  /*
2155  * Skip any whitespace before parsing the integer.
2156  */
2157  *src += strspace_len(*src);
2158 
2159  Assert(len <= DCH_MAX_ITEM_SIZ);
2160  used = (int) strlcpy(copy, *src, len + 1);
2161 
2162  if (S_FM(node->suffix) || is_next_separator(node))
2163  {
2164  /*
2165  * This node is in Fill Mode, or the next node is known to be a
2166  * non-digit value, so we just slurp as many characters as we can get.
2167  */
2168  errno = 0;
2169  result = strtol(init, src, 10);
2170  }
2171  else
2172  {
2173  /*
2174  * We need to pull exactly the number of characters given in 'len' out
2175  * of the string, and convert those.
2176  */
2177  char *last;
2178 
2179  if (used < len)
2180  ereport(ERROR,
2181  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2182  errmsg("source string too short for \"%s\" formatting field",
2183  node->key->name),
2184  errdetail("Field requires %d characters, but only %d "
2185  "remain.",
2186  len, used),
2187  errhint("If your source string is not fixed-width, try "
2188  "using the \"FM\" modifier.")));
2189 
2190  errno = 0;
2191  result = strtol(copy, &last, 10);
2192  used = last - copy;
2193 
2194  if (used > 0 && used < len)
2195  ereport(ERROR,
2196  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2197  errmsg("invalid value \"%s\" for \"%s\"",
2198  copy, node->key->name),
2199  errdetail("Field requires %d characters, but only %d "
2200  "could be parsed.", len, used),
2201  errhint("If your source string is not fixed-width, try "
2202  "using the \"FM\" modifier.")));
2203 
2204  *src += used;
2205  }
2206 
2207  if (*src == init)
2208  ereport(ERROR,
2209  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2210  errmsg("invalid value \"%s\" for \"%s\"",
2211  copy, node->key->name),
2212  errdetail("Value must be an integer.")));
2213 
2214  if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2215  ereport(ERROR,
2216  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2217  errmsg("value for \"%s\" in source string is out of range",
2218  node->key->name),
2219  errdetail("Value must be in the range %d to %d.",
2220  INT_MIN, INT_MAX)));
2221 
2222  if (dest != NULL)
2223  from_char_set_int(dest, (int) result, node);
2224  return *src - init;
2225 }
int errhint(const char *fmt,...)
Definition: elog.c:987
const KeyWord * key
Definition: formatting.c:164
static void from_char_set_int(int *dest, const int value, const FormatNode *node)
Definition: formatting.c:2114
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static bool is_next_separator(FormatNode *n)
Definition: formatting.c:2017
#define S_FM(_s)
Definition: formatting.c:517
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
const char * name
Definition: formatting.c:154
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int strspace_len(char *str)
Definition: formatting.c:2073
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static void init(bool is_no_vacuum)
Definition: pgbench.c:2571
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:113
static int from_char_seq_search ( int *  dest,
char **  src,
const char *const *  array,
int  type,
int  max,
FormatNode node 
)
static

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

2327 {
2328  int len;
2329 
2330  *dest = seq_search(*src, array, type, max, &len);
2331  if (len <= 0)
2332  {
2333  char copy[DCH_MAX_ITEM_SIZ + 1];
2334 
2335  Assert(max <= DCH_MAX_ITEM_SIZ);
2336  strlcpy(copy, *src, max + 1);
2337 
2338  ereport(ERROR,
2339  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2340  errmsg("invalid value \"%s\" for \"%s\"",
2341  copy, node->key->name),
2342  errdetail("The given value did not match any of the allowed "
2343  "values for this field.")));
2344  }
2345  *src += len;
2346  return len;
2347 }
const KeyWord * key
Definition: formatting.c:164
static int seq_search(char *name, const char *const *array, int type, int max, int *len)
Definition: formatting.c:2247
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:154
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:671
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DCH_MAX_ITEM_SIZ
Definition: formatting.c:113
static void from_char_set_int ( int *  dest,
const int  value,
const FormatNode node 
)
static

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

2115 {
2116  if (*dest != 0 && *dest != value)
2117  ereport(ERROR,
2118  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2119  errmsg("conflicting values for \"%s\" field in formatting string",
2120  node->key->name),
2121  errdetail("This value contradicts a previous setting for "
2122  "the same field type.")));
2123  *dest = value;
2124 }
static struct @76 value
const KeyWord * key
Definition: formatting.c:164
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:154
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void from_char_set_mode ( TmFromChar tmfc,
const FromCharDateMode  mode 
)
static

Definition at line 2092 of file formatting.c.

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

Referenced by DCH_from_char().

2093 {
2094  if (mode != FROM_CHAR_DATE_NONE)
2095  {
2096  if (tmfc->mode == FROM_CHAR_DATE_NONE)
2097  tmfc->mode = mode;
2098  else if (tmfc->mode != mode)
2099  ereport(ERROR,
2100  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2101  errmsg("invalid combination of date conventions"),
2102  errhint("Do not mix Gregorian and ISO week date "
2103  "conventions in a formatting template.")));
2104  }
2105 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
FromCharDateMode mode
Definition: formatting.c:406
#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 4178 of file formatting.c.

References elog, and NULL.

Referenced by NUM_processor().

4179 {
4180  char *result,
4181  *p = strchr(num, '.');
4182 
4183 #ifdef DEBUG_TO_FROM_CHAR
4184  elog(DEBUG_elog_output, "get_last_relevant_decnum()");
4185 #endif
4186 
4187  if (!p)
4188  return NULL;
4189 
4190  result = p;
4191 
4192  while (*(++p))
4193  {
4194  if (*p != '0')
4195  result = p;
4196  }
4197 
4198  return result;
4199 }
#define NULL
Definition: c.h:226
#define elog
Definition: elog.h:219
static const char * get_th ( char *  num,
int  type 
)
static

Definition at line 1388 of file formatting.c.

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

Referenced by NUM_processor(), and str_numth().

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

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

Referenced by parse_format().

1005 {
1006  int poz;
1007 
1008  if (!KeyWord_INDEX_FILTER(*str))
1009  return NULL;
1010 
1011  if ((poz = *(index + (*str - ' '))) > -1)
1012  {
1013  const KeyWord *k = kw + poz;
1014 
1015  do
1016  {
1017  if (strncmp(str, k->name, k->len) == 0)
1018  return k;
1019  k++;
1020  if (!k->name)
1021  return NULL;
1022  } while (*str == *k->name);
1023  }
1024  return NULL;
1025 }
Definition: type.h:90
const char * name
Definition: formatting.c:154
int len
Definition: formatting.c:155
#define KeyWord_INDEX_FILTER(_c)
Definition: formatting.c:107
#define NULL
Definition: c.h:226
Datum int4_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5246 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_P, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, sign, snprintf(), val, and value.

5247 {
5249  text *fmt = PG_GETARG_TEXT_P(1);
5250  NUMDesc Num;
5251  FormatNode *format;
5252  text *result;
5253  bool shouldFree;
5254  int out_pre_spaces = 0,
5255  sign = 0;
5256  char *numstr,
5257  *orgnum;
5258 
5260 
5261  /*
5262  * On DateType depend part (int32)
5263  */
5264  if (IS_ROMAN(&Num))
5265  numstr = orgnum = int_to_roman(value);
5266  else if (IS_EEEE(&Num))
5267  {
5268  /* we can do it easily because float8 won't lose any precision */
5269  float8 val = (float8) value;
5270 
5271  orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5272  snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
5273 
5274  /*
5275  * Swap a leading positive sign for a space.
5276  */
5277  if (*orgnum == '+')
5278  *orgnum = ' ';
5279 
5280  numstr = orgnum;
5281  }
5282  else
5283  {
5284  int numstr_pre_len;
5285 
5286  if (IS_MULTI(&Num))
5287  {
5289  Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
5290  Num.pre += Num.multi;
5291  }
5292  else
5293  {
5295  Int32GetDatum(value)));
5296  }
5297 
5298  if (*orgnum == '-')
5299  {
5300  sign = '-';
5301  orgnum++;
5302  }
5303  else
5304  sign = '+';
5305 
5306  numstr_pre_len = strlen(orgnum);
5307 
5308  /* post-decimal digits? Pad out with zeros. */
5309  if (Num.post)
5310  {
5311  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5312  strcpy(numstr, orgnum);
5313  *(numstr + numstr_pre_len) = '.';
5314  memset(numstr + numstr_pre_len + 1, '0', Num.post);
5315  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
5316  }
5317  else
5318  numstr = orgnum;
5319 
5320  /* needs padding? */
5321  if (numstr_pre_len < Num.pre)
5322  out_pre_spaces = Num.pre - numstr_pre_len;
5323  /* overflowed prefix digit format? */
5324  else if (numstr_pre_len > Num.pre)
5325  {
5326  numstr = (char *) palloc(Num.pre + Num.post + 2);
5327  fill_str(numstr, '#', Num.pre + Num.post + 1);
5328  *(numstr + Num.pre) = '.';
5329  }
5330  }
5331 
5333  PG_RETURN_TEXT_P(result);
5334 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
static struct @76 value
#define MAXDOUBLEWIDTH
Definition: formatting.c:121
#define IS_EEEE(_f)
Definition: formatting.c:353
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
#define NUM_TOCHAR_finish
Definition: formatting.c:5038
#define IS_ROMAN(_f)
Definition: formatting.c:351
signed int int32
Definition: c.h:253
#define NUM_TOCHAR_prepare
Definition: formatting.c:5025
double float8
Definition: c.h:378
#define DatumGetCString(X)
Definition: postgres.h:574
#define IS_MULTI(_f)
Definition: formatting.c:352
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3849
static char * int_to_roman(int number)
Definition: formatting.c:4047
int pre
Definition: formatting.c:304
Datum int4out(PG_FUNCTION_ARGS)
Definition: int.c:277
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
int post
Definition: formatting.c:304
#define Int32GetDatum(X)
Definition: postgres.h:487
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int multi
Definition: formatting.c:304
Definition: c.h:435
static char format
Definition: pg_basebackup.c:83
long val
Definition: informix.c:689
Datum int8_to_char ( PG_FUNCTION_ARGS  )

Definition at line 5341 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_P, PG_RETURN_TEXT_P, NUMDesc::post, NUMDesc::pre, sign, val, and value.

5342 {
5343  int64 value = PG_GETARG_INT64(0);
5344  text *fmt = PG_GETARG_TEXT_P(1);
5345  NUMDesc Num;
5346  FormatNode *format;
5347  text *result;
5348  bool shouldFree;
5349  int out_pre_spaces = 0,
5350  sign = 0;
5351  char *numstr,
5352  *orgnum;
5353 
5355 
5356  /*
5357  * On DateType depend part (int32)
5358  */
5359  if (IS_ROMAN(&Num))
5360  {
5361  /* Currently don't support int8 conversion to roman... */
5362  numstr = orgnum = int_to_roman(DatumGetInt32(
5364  }
5365  else if (IS_EEEE(&Num))
5366  {
5367  /* to avoid loss of precision, must go via numeric not float8 */
5368  Numeric val;
5369 
5371  Int64GetDatum(value)));
5372  orgnum = numeric_out_sci(val, Num.post);
5373 
5374  /*
5375  * numeric_out_sci() does not emit a sign for positive numbers. We
5376  * need to add a space in this case so that positive and negative
5377  * numbers are aligned. We don't have to worry about NaN here.
5378  */
5379  if (*orgnum != '-')
5380  {
5381  numstr = (char *) palloc(strlen(orgnum) + 2);
5382  *numstr = ' ';
5383  strcpy(numstr + 1, orgnum);
5384  }
5385  else
5386  {
5387  numstr = orgnum;
5388  }
5389  }
5390  else
5391  {
5392  int numstr_pre_len;
5393 
5394  if (IS_MULTI(&Num))
5395  {
5396  double multi = pow((double) 10, (double) Num.multi);
5397 
5399  Int64GetDatum(value),
5401  Float8GetDatum(multi))));
5402  Num.pre += Num.multi;
5403  }
5404 
5406  Int64GetDatum(value)));
5407 
5408  if (*orgnum == '-')
5409  {
5410  sign = '-';
5411  orgnum++;
5412  }
5413  else
5414  sign = '+';
5415 
5416  numstr_pre_len = strlen(orgnum);
5417 
5418  /* post-decimal digits? Pad out with zeros. */
5419  if (Num.post)
5420  {
5421  numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5422  strcpy(numstr, orgnum);
5423  *(numstr + numstr_pre_len) = '.';
5424  memset(numstr + numstr_pre_len + 1, '0', Num.post);
5425  *(numstr + numstr_pre_len + Num.post + 1) = '\0';
5426  }
5427  else
5428  numstr = orgnum;
5429 
5430  /* needs padding? */
5431  if (numstr_pre_len < Num.pre)
5432  out_pre_spaces = Num.pre - numstr_pre_len;
5433  /* overflowed prefix digit format? */
5434  else if (numstr_pre_len > Num.pre)
5435  {
5436  numstr = (char *) palloc(Num.pre + Num.post + 2);
5437  fill_str(numstr, '#', Num.pre + Num.post + 1);
5438  *(numstr + Num.pre) = '.';
5439  }
5440  }
5441 
5443  PG_RETURN_TEXT_P(result);
5444 }
static struct @76 value
#define DatumGetInt32(X)
Definition: postgres.h:480
#define IS_EEEE(_f)
Definition: formatting.c:353
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
#define NUM_TOCHAR_finish
Definition: formatting.c:5038
#define IS_ROMAN(_f)
Definition: formatting.c:351
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:2126
#define NUM_TOCHAR_prepare
Definition: formatting.c:5025
#define DatumGetCString(X)
Definition: postgres.h:574
#define IS_MULTI(_f)
Definition: formatting.c:352
#define DatumGetInt64(X)
Definition: postgres.h:615
char sign
Definition: informix.c:693
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3849
Datum int8mul(PG_FUNCTION_ARGS)
Definition: int8.c:555
static char * int_to_roman(int number)
Definition: formatting.c:4047
Datum dtoi8(PG_FUNCTION_ARGS)
Definition: int8.c:1343
int pre
Definition: formatting.c:304
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
int post
Definition: formatting.c:304
#define DatumGetNumeric(X)
Definition: numeric.h:49
Datum int84(PG_FUNCTION_ARGS)
Definition: int8.c:1287
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int multi
Definition: formatting.c:304
Definition: c.h:435
static char format
Definition: pg_basebackup.c:83
char * numeric_out_sci(Numeric num, int scale)
Definition: numeric.c:719
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
long val
Definition: informix.c:689
Datum int8out(PG_FUNCTION_ARGS)
Definition: int8.c:158
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:557
static char * int_to_roman ( int  number)
static

Definition at line 4047 of file formatting.c.

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

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

4048 {
4049  int len = 0,
4050  num = 0;
4051  char *p = NULL,
4052  *result,
4053  numstr[5];
4054 
4055  result = (char *) palloc(16);
4056  *result = '\0';
4057 
4058  if (number > 3999 || number < 1)
4059  {
4060  fill_str(result, '#', 15);
4061  return result;
4062  }
4063  len = snprintf(numstr, sizeof(numstr), "%d", number);
4064 
4065  for (p = numstr; *p != '\0'; p++, --len)
4066  {
4067  num = *p - 49; /* 48 ascii + 1 */
4068  if (num < 0)
4069  continue;
4070 
4071  if (len > 3)
4072  {
4073  while (num-- != -1)
4074  strcat(result, "M");
4075  }
4076  else
4077  {
4078  if (len == 3)
4079  strcat(result, rm100[num]);
4080  else if (len == 2)
4081  strcat(result, rm10[num]);
4082  else if (len == 1)
4083  strcat(result, rm1[num]);
4084  }
4085  }
4086  return result;
4087 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static const char *const rm10[]
Definition: formatting.c:269
static const char *const rm1[]
Definition: formatting.c:268
static char * fill_str(char *str, int c, int max)
Definition: formatting.c:3849
static const char *const rm100[]
Definition: formatting.c:270
#define NULL
Definition: c.h:226
void * palloc(Size size)
Definition: mcxt.c:891
Datum interval_to_char ( PG_FUNCTION_ARGS  )

Definition at line 3458 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_P, 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, VARHDRSZ, VARSIZE, and ZERO_tmtc.

3459 {
3460  Interval *it = PG_GETARG_INTERVAL_P(0);
3461  text *fmt = PG_GETARG_TEXT_P(1),
3462  *res;
3463  TmToChar tmtc;
3464  struct pg_tm *tm;
3465 
3466  if ((VARSIZE(fmt) - VARHDRSZ) <= 0)
3467  PG_RETURN_NULL();
3468 
3469  ZERO_tmtc(&tmtc);
3470  tm = tmtcTm(&tmtc);
3471 
3472  if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
3473  PG_RETURN_NULL();
3474 
3475  /* wday is meaningless, yday approximates the total span in days */
3476  tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
3477 
3478  if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
3479  PG_RETURN_NULL();
3480 
3481  PG_RETURN_TEXT_P(res);
3482 }
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:57
static text * datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
Definition: formatting.c:3321
#define VARSIZE(PTR)
Definition: postgres.h:306
#define ZERO_tmtc(_X)
Definition: formatting.c:473
#define VARHDRSZ
Definition: c.h:441
Definition: pgtime.h:25
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define tmtcFsec(_X)
Definition: formatting.c:464
static struct pg_tm tm
Definition: localtime.c:103
#define MONTHS_PER_YEAR
Definition: timestamp.h:81
int interval2tm(Interval span, struct pg_tm *tm, fsec_t *fsec)
Definition: timestamp.c:2140
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define DAYS_PER_MONTH
Definition: timestamp.h:89
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
int tm_year
Definition: pgtime.h:32
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int tm_yday
Definition: pgtime.h:34
Definition: c.h:435
#define tmtcTm(_X)
Definition: formatting.c:462
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static bool is_next_separator ( FormatNode n)
static

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

2018 {
2019  if (n->type == NODE_TYPE_END)
2020  return FALSE;
2021 
2022  if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
2023  return TRUE;
2024 
2025  /*
2026  * Next node
2027  */
2028  n++;
2029 
2030  /* end of format string is treated like a non-digit separator */
2031  if (n->type == NODE_TYPE_END)
2032  return TRUE;
2033 
2034  if (n->type == NODE_TYPE_ACTION)
2035  {
2036  if (n->key->is_digit)
2037  return FALSE;
2038 
2039  return TRUE;
2040  }
2041  else if (isdigit((unsigned char) n->character))
2042  return FALSE;
2043 
2044  return TRUE; /* some non-digit input (separator) */
2045 }
#define NODE_TYPE_END
Definition: formatting.c:169
const KeyWord * key
Definition: formatting.c:164
#define S_THth(_s)
Definition: formatting.c:511
#define NODE_TYPE_ACTION
Definition: formatting.c:170
#define FALSE
Definition: c.h:218
char character
Definition: formatting.c:165
#define TRUE
Definition: c.h:214
bool is_digit
Definition: formatting.c:157
static FormatNode * NUM_cache ( int  len,
NUMDesc Num,
text pars_str,
bool shouldFree 
)
static

Definition at line 3989 of file formatting.c.

References NUMDesc::flag, format, NUMCacheEntry::format, NUMDesc::lsign, NUMDesc::multi, NUMDesc::need_locale, NULL, 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().

3990 {
3991  FormatNode *format = NULL;
3992  char *str;
3993 
3994  str = text_to_cstring(pars_str);
3995 
3996  if (len > NUM_CACHE_SIZE)
3997  {
3998  /*
3999  * Allocate new memory if format picture is bigger than static cache
4000  * and do not use cache (call parser always)
4001  */
4002  format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
4003 
4004  *shouldFree = true;
4005 
4006  zeroize_NUM(Num);
4007 
4008  parse_format(format, str, NUM_keywords,
4009  NULL, NUM_index, NUM_TYPE, Num);
4010  }
4011  else
4012  {
4013  /*
4014  * Use cache buffers
4015  */
4016  NUMCacheEntry *ent = NUM_cache_fetch(str);
4017 
4018  *shouldFree = false;
4019 
4020  format = ent->format;
4021 
4022  /*
4023  * Copy cache to used struct
4024  */
4025  Num->flag = ent->Num.flag;
4026  Num->lsign = ent->Num.lsign;
4027  Num->pre = ent->Num.pre;
4028  Num->post = ent->Num.post;
4029  Num->pre_lsign_num = ent->Num.pre_lsign_num;
4030  Num->need_locale = ent->Num.need_locale;
4031  Num->multi = ent->Num.multi;
4032  Num->zero_start = ent->Num.zero_start;
4033  Num->zero_end = ent->Num.zero_end;
4034  }
4035 
4036 #ifdef DEBUG_TO_FROM_CHAR
4037  /* dump_node(format, len); */
4038  dump_index(NUM_keywords, NUM_index);
4039 #endif
4040 
4041  pfree(str);
4042  return format;
4043 }
NUMDesc Num
Definition: formatting.c:387
int need_locale
Definition: formatting.c:304
struct FormatNode FormatNode
Definition: formatting.c:150
int flag
Definition: formatting.c:304
#define NUM_CACHE_SIZE
Definition: formatting.c:368
void pfree(void *pointer)
Definition: mcxt.c:992
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:1223
int pre
Definition: formatting.c:304
#define NUM_TYPE
Definition: formatting.c:100
static NUMCacheEntry * NUM_cache_fetch(const char *str)
Definition: formatting.c:3961
int post
Definition: formatting.c:304
#define NULL
Definition: c.h:226
int zero_end
Definition: formatting.c:304
int pre_lsign_num
Definition: formatting.c:304
static const KeyWord NUM_keywords[]
Definition: formatting.c:821
char * text_to_cstring(const text *t)
Definition: varlena.c:184
void * palloc(Size size)
Definition: mcxt.c:891
FormatNode format[NUM_CACHE_SIZE+1]
Definition: formatting.c:383
int multi
Definition: formatting.c:304
int lsign
Definition: formatting.c:304
int zero_start
Definition: formatting.c:304
static char format
Definition: pg_basebackup.c:83
static const int NUM_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:893
#define zeroize_NUM(_n)
Definition: formatting.c:3856
static NUMCacheEntry * NUM_cache_fetch ( const char *  str)
static

Definition at line 3961 of file formatting.c.

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

Referenced by NUM_cache().

3962 {
3963  NUMCacheEntry *ent;
3964 
3965  if ((ent = NUM_cache_search(str)) == NULL)
3966  {
3967  /*
3968  * Not in the cache, must run parser and save a new format-picture to
3969  * the cache. Do not mark the cache entry valid until parsing
3970  * succeeds.
3971  */
3972  ent = NUM_cache_getnew(str);
3973 
3974  zeroize_NUM(&ent->Num);
3975 
3976  parse_format(ent->format, str, NUM_keywords,
3977  NULL, NUM_index, NUM_TYPE, &ent->Num);
3978 
3979  ent->valid = true;
3980  }
3981  return ent;
3982 }
static NUMCacheEntry * NUM_cache_getnew(const char *str)
Definition: formatting.c:3871
NUMDesc Num
Definition: formatting.c:387
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:1223
static NUMCacheEntry * NUM_cache_search(const char *str)
Definition: formatting.c:3933
#define NUM_TYPE
Definition: formatting.c:100
#define NULL
Definition: c.h:226
static const KeyWord NUM_keywords[]
Definition: formatting.c:821
FormatNode format[NUM_CACHE_SIZE+1]
Definition: formatting.c:383
static const int NUM_index[KeyWord_INDEX_SIZE]
Definition: formatting.c:893
#define zeroize_NUM(_n)
Definition: formatting.c:3856
static NUMCacheEntry * NUM_cache_getnew ( const char *  str)
static

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

3872 {
3873  NUMCacheEntry *ent;
3874 
3875  /* counter overflow check - paranoia? */
3876  if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
3877  {
3878  NUMCounter = 0;
3879 
3880  for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
3881  ent->age = (++NUMCounter);
3882  }
3883 
3884  /*
3885  * If cache is full, remove oldest entry (or recycle first not-valid one)
3886  */
3887  if (n_NUMCache >=