formatting.c cleanup
The file formatting.c contains some hard to read and understand code.
For the attached patch series, I made a few more or less mechanical
passes over it to modernize the code a bit, renamed some symbols to be
clearer, adjusted some types to make things more self-documenting,
removed some redundant code to make some things more compact. I hope
this helps a bit.
Attachments:
v1-0001-formatting.c-cleanup-Remove-dashes-in-comments.patchtext/plain; charset=UTF-8; name=v1-0001-formatting.c-cleanup-Remove-dashes-in-comments.patchDownload
From 4dcecd7bfd306cdca86e8ac529043776af06c175 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 01/13] formatting.c cleanup: Remove dashes in comments
This saves some vertical space and makes the comments style more
consistent with the rest of the code.
---
src/backend/utils/adt/formatting.c | 174 ++++++++++-------------------
1 file changed, 59 insertions(+), 115 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 78e19ac39ac..3adbfcd5592 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,4 +1,4 @@
-/* -----------------------------------------------------------------------
+/*-------------------------------------------------------------------------
* formatting.c
*
* src/backend/utils/adt/formatting.c
@@ -54,7 +54,7 @@
* than Oracle :-),
* to_char('Hello', 'X X X X X') -> 'H e l l o'
*
- * -----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
#ifdef DEBUG_TO_FROM_CHAR
@@ -92,32 +92,28 @@
#include "varatt.h"
-/* ----------
+/*
* Routines flags
- * ----------
*/
#define DCH_FLAG 0x1 /* DATE-TIME flag */
#define NUM_FLAG 0x2 /* NUMBER flag */
#define STD_FLAG 0x4 /* STANDARD flag */
-/* ----------
+/*
* KeyWord Index (ascii from position 32 (' ') to 126 (~))
- * ----------
*/
#define KeyWord_INDEX_SIZE ('~' - ' ')
#define KeyWord_INDEX_FILTER(_c) ((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
-/* ----------
+/*
* Maximal length of one node
- * ----------
*/
#define DCH_MAX_ITEM_SIZ 12 /* max localized day name */
#define NUM_MAX_ITEM_SIZ 8 /* roman number (RN has 15 chars) */
-/* ----------
+/*
* Format parser structs
- * ----------
*/
typedef struct
{
@@ -127,9 +123,8 @@ typedef struct
type; /* prefix / postfix */
} KeySuffix;
-/* ----------
+/*
* FromCharDateMode
- * ----------
*
* This value is used to nominate one of several distinct (and mutually
* exclusive) date conventions that a keyword can belong to.
@@ -171,9 +166,8 @@ typedef struct
#define CLOCK_12_HOUR 1
-/* ----------
+/*
* Full months
- * ----------
*/
static const char *const months_full[] = {
"January", "February", "March", "April", "May", "June", "July",
@@ -184,9 +178,9 @@ static const char *const days_short[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
};
-/* ----------
+/*
* AD / BC
- * ----------
+ *
* There is no 0 AD. Years go from 1 BC to 1 AD, so we make it
* positive and map year == -1 to year zero, and shift all negative
* years up one. For interval years, we just return the year.
@@ -216,9 +210,8 @@ 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};
-/* ----------
+/*
* AM / PM
- * ----------
*/
#define A_M_STR "A.M."
#define a_m_STR "a.m."
@@ -243,11 +236,10 @@ static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_S
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};
-/* ----------
+/*
* Months in roman-numeral
* (Must be in reverse order for seq_search (in FROM_CHAR), because
* 'VIII' must have higher precedence than 'V')
- * ----------
*/
static const char *const rm_months_upper[] =
{"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
@@ -255,9 +247,8 @@ static const char *const rm_months_upper[] =
static const char *const rm_months_lower[] =
{"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
-/* ----------
+/*
* Roman numerals
- * ----------
*/
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};
@@ -289,23 +280,20 @@ static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "D
*/
#define MAX_ROMAN_LEN 15
-/* ----------
+/*
* Ordinal postfixes
- * ----------
*/
static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL};
static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
-/* ----------
+/*
* Flags & Options:
- * ----------
*/
#define TH_UPPER 1
#define TH_LOWER 2
-/* ----------
+/*
* Number description struct
- * ----------
*/
typedef struct
{
@@ -320,9 +308,8 @@ typedef struct
need_locale; /* needs it locale */
} NUMDesc;
-/* ----------
+/*
* Flags for NUMBER version
- * ----------
*/
#define NUM_F_DECIMAL (1 << 1)
#define NUM_F_LDECIMAL (1 << 2)
@@ -343,9 +330,8 @@ typedef struct
#define NUM_LSIGN_POST 1
#define NUM_LSIGN_NONE 0
-/* ----------
+/*
* Tests
- * ----------
*/
#define IS_DECIMAL(_f) ((_f)->flag & NUM_F_DECIMAL)
#define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
@@ -360,7 +346,7 @@ typedef struct
#define IS_MULTI(_f) ((_f)->flag & NUM_F_MULTI)
#define IS_EEEE(_f) ((_f)->flag & NUM_F_EEEE)
-/* ----------
+/*
* Format picture cache
*
* We will cache datetime format pictures up to DCH_CACHE_SIZE bytes long;
@@ -376,7 +362,6 @@ typedef struct
*
* The max number of entries in each cache is DCH_CACHE_ENTRIES
* resp. NUM_CACHE_ENTRIES.
- * ----------
*/
#define DCH_CACHE_OVERHEAD \
MAXALIGN(sizeof(bool) + sizeof(int))
@@ -419,9 +404,8 @@ static NUMCacheEntry *NUMCache[NUM_CACHE_ENTRIES];
static int n_NUMCache = 0; /* current number of entries */
static int NUMCounter = 0; /* aging-event counter */
-/* ----------
+/*
* For char->date/time conversion
- * ----------
*/
typedef struct
{
@@ -463,9 +447,8 @@ struct fmt_tz /* do_to_timestamp's timezone info output */
int gmtoffset; /* GMT offset in seconds */
};
-/* ----------
+/*
* Debug
- * ----------
*/
#ifdef DEBUG_TO_FROM_CHAR
#define DEBUG_TMFC(_X) \
@@ -484,13 +467,12 @@ struct fmt_tz /* do_to_timestamp's timezone info output */
#define DEBUG_TM(_X)
#endif
-/* ----------
+/*
* Datetime to char conversion
*
* To support intervals as well as timestamps, we use a custom "tm" struct
* that is almost like struct pg_tm, but has a 64-bit tm_hour field.
* We omit the tm_isdst and tm_zone fields, which are not used here.
- * ----------
*/
struct fmt_tm
{
@@ -561,9 +543,8 @@ do { \
* KeyWord definitions
*****************************************************************************/
-/* ----------
+/*
* Suffixes (FormatNode.suffix is an OR of these codes)
- * ----------
*/
#define DCH_S_FM 0x01
#define DCH_S_TH 0x02
@@ -571,9 +552,8 @@ do { \
#define DCH_S_SP 0x08
#define DCH_S_TM 0x10
-/* ----------
+/*
* Suffix tests
- * ----------
*/
#define S_THth(_s) ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
#define S_TH(_s) (((_s) & DCH_S_TH) ? 1 : 0)
@@ -585,9 +565,8 @@ do { \
#define S_SP(_s) (((_s) & DCH_S_SP) ? 1 : 0)
#define S_TM(_s) (((_s) & DCH_S_TM) ? 1 : 0)
-/* ----------
+/*
* Suffixes definition for DATE-TIME TO/FROM CHAR
- * ----------
*/
#define TM_SUFFIX_LEN 2
@@ -604,7 +583,7 @@ static const KeySuffix DCH_suff[] = {
};
-/* ----------
+/*
* Format-pictures (KeyWord).
*
* The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted
@@ -628,8 +607,6 @@ static const KeySuffix DCH_suff[] = {
* 1) see in index to index['M' - 32],
* 2) take keywords position (enum DCH_MI) from index
* 3) run sequential search in keywords[] from this position
- *
- * ----------
*/
typedef enum
@@ -794,9 +771,8 @@ typedef enum
_NUM_last_
} NUM_poz;
-/* ----------
+/*
* KeyWords for DATE-TIME version
- * ----------
*/
static const KeyWord DCH_keywords[] = {
/* name, len, id, is_digit, date_mode */
@@ -917,11 +893,10 @@ static const KeyWord DCH_keywords[] = {
{NULL, 0, 0, 0, 0}
};
-/* ----------
+/*
* KeyWords for NUMBER version
*
* The is_digit and date_mode fields are not relevant here.
- * ----------
*/
static const KeyWord NUM_keywords[] = {
/* name, len, id is in Index */
@@ -967,9 +942,8 @@ static const KeyWord NUM_keywords[] = {
};
-/* ----------
+/*
* KeyWords index for DATE-TIME version
- * ----------
*/
static const int DCH_index[KeyWord_INDEX_SIZE] = {
/*
@@ -991,9 +965,8 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = {
/*---- chars over 126 are skipped ----*/
};
-/* ----------
+/*
* KeyWords index for NUMBER version
- * ----------
*/
static const int NUM_index[KeyWord_INDEX_SIZE] = {
/*
@@ -1015,9 +988,8 @@ static const int NUM_index[KeyWord_INDEX_SIZE] = {
/*---- chars over 126 are skipped ----*/
};
-/* ----------
+/*
* Number processor struct
- * ----------
*/
typedef struct NUMProc
{
@@ -1062,9 +1034,8 @@ typedef struct NUMProc
#define AMOUNT_TEST(s) (Np->inout_p <= Np->inout + (input_len - (s)))
-/* ----------
+/*
* Functions
- * ----------
*/
static const KeyWord *index_seq_search(const char *str, const KeyWord *kw,
const int *index);
@@ -1125,11 +1096,10 @@ static NUMCacheEntry *NUM_cache_search(const char *str);
static NUMCacheEntry *NUM_cache_fetch(const char *str);
-/* ----------
+/*
* Fast sequential search, use index for data selection which
* go to seq. cycle (it is very fast for unwanted strings)
* (can't be used binary search in format parsing)
- * ----------
*/
static const KeyWord *
index_seq_search(const char *str, const KeyWord *kw, const int *index)
@@ -1181,9 +1151,8 @@ is_separator_char(const char *str)
!(*str >= '0' && *str <= '9'));
}
-/* ----------
+/*
* Prepare NUMDesc (number description struct) via FormatNode struct
- * ----------
*/
static void
NUMDesc_prepare(NUMDesc *num, FormatNode *n)
@@ -1364,12 +1333,11 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
errdetail("\"RN\" may only be used together with \"FM\".")));
}
-/* ----------
+/*
* Format parser, search small keywords and keyword's suffixes, and make
* format-node tree.
*
* for DATE-TIME & NUMBER version
- * ----------
*/
static void
parse_format(FormatNode *node, const char *str, const KeyWord *kw,
@@ -1514,9 +1482,8 @@ parse_format(FormatNode *node, const char *str, const KeyWord *kw,
n->suffix = 0;
}
-/* ----------
+/*
* DEBUG: Dump the FormatNode Tree (debug)
- * ----------
*/
#ifdef DEBUG_TO_FROM_CHAR
@@ -1554,10 +1521,9 @@ dump_node(FormatNode *node, int max)
* Private utils
*****************************************************************************/
-/* ----------
+/*
* Return ST/ND/RD/TH for simple (1..9) numbers
* type --> 0 upper, 1 lower
- * ----------
*/
static const char *
get_th(char *num, int type)
@@ -1601,10 +1567,9 @@ get_th(char *num, int type)
}
}
-/* ----------
+/*
* Convert string-number to ordinal string-number
* type --> 0 upper, 1 lower
- * ----------
*/
static char *
str_numth(char *dest, char *num, int type)
@@ -2006,11 +1971,10 @@ asc_toupper_z(const char *buff)
/* asc_initcap_z is not currently needed */
-/* ----------
+/*
* Skip TM / th in FROM_CHAR
*
* If S_THth is on, skip two chars, assuming there are two available
- * ----------
*/
#define SKIP_THth(ptr, _suf) \
do { \
@@ -2023,10 +1987,9 @@ asc_toupper_z(const char *buff)
#ifdef DEBUG_TO_FROM_CHAR
-/* -----------
+/*
* DEBUG: Call for debug and for index checking; (Show ASCII char
* and defined keyword for each used position
- * ----------
*/
static void
dump_index(const KeyWord *k, const int *index)
@@ -2055,9 +2018,8 @@ dump_index(const KeyWord *k, const int *index)
}
#endif /* DEBUG */
-/* ----------
+/*
* Return true if next format picture is not digit value
- * ----------
*/
static bool
is_next_separator(FormatNode *n)
@@ -2498,10 +2460,9 @@ from_char_seq_search(int *dest, const char **src, const char *const *array,
return true;
}
-/* ----------
+/*
* Process a TmToChar struct as denoted by a list of FormatNodes.
* The formatted data is written to the string pointed to by 'out'.
- * ----------
*/
static void
DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
@@ -3992,9 +3953,8 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
* Public routines
***************************************************************************/
-/* -------------------
+/*
* TIMESTAMP to_char()
- * -------------------
*/
Datum
timestamp_to_char(PG_FUNCTION_ARGS)
@@ -4068,9 +4028,8 @@ timestamptz_to_char(PG_FUNCTION_ARGS)
}
-/* -------------------
+/*
* INTERVAL to_char()
- * -------------------
*/
Datum
interval_to_char(PG_FUNCTION_ARGS)
@@ -4107,12 +4066,11 @@ interval_to_char(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(res);
}
-/* ---------------------
+/*
* TO_TIMESTAMP()
*
* Make Timestamp from date_str which is formatted at argument 'fmt'
* ( to_timestamp is reverse to_char() )
- * ---------------------
*/
Datum
to_timestamp(PG_FUNCTION_ARGS)
@@ -4148,10 +4106,9 @@ to_timestamp(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMP(result);
}
-/* ----------
+/*
* TO_DATE
* Make Date from date_str which is formatted at argument 'fmt'
- * ----------
*/
Datum
to_date(PG_FUNCTION_ARGS)
@@ -4998,9 +4955,8 @@ NUM_cache_fetch(const char *str)
return ent;
}
-/* ----------
+/*
* Cache routine for NUM to_char version
- * ----------
*/
static FormatNode *
NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
@@ -5271,9 +5227,8 @@ roman_to_int(NUMProc *Np, int input_len)
}
-/* ----------
+/*
* Locale
- * ----------
*/
static void
NUM_prepare_locale(NUMProc *Np)
@@ -5349,13 +5304,12 @@ NUM_prepare_locale(NUMProc *Np)
}
}
-/* ----------
+/*
* Return pointer of last relevant number after decimal point
* 12.0500 --> last relevant is '5'
* 12.0000 --> last relevant is '.'
* If there is no decimal point, return NULL (which will result in same
* behavior as if FM hadn't been specified).
- * ----------
*/
static char *
get_last_relevant_decnum(char *num)
@@ -5381,9 +5335,8 @@ get_last_relevant_decnum(char *num)
return result;
}
-/* ----------
+/*
* Number extraction for TO_NUMBER()
- * ----------
*/
static void
NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
@@ -5596,9 +5549,8 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
*(_n)->number == '0' && \
(_n)->Num->post != 0)
-/* ----------
+/*
* Add digit or sign to number-string
- * ----------
*/
static void
NUM_numpart_to_char(NUMProc *Np, int id)
@@ -6267,10 +6219,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
}
}
-/* ----------
+/*
* MACRO: Start part of NUM - for all NUM's to_char variants
* (sorry, but I hate copy same code - macro is better..)
- * ----------
*/
#define NUM_TOCHAR_prepare \
do { \
@@ -6281,9 +6232,8 @@ do { \
format = NUM_cache(len, &Num, fmt, &shouldFree); \
} while (0)
-/* ----------
+/*
* MACRO: Finish part of NUM
- * ----------
*/
#define NUM_TOCHAR_finish \
do { \
@@ -6303,9 +6253,8 @@ do { \
SET_VARSIZE(result, len + VARHDRSZ); \
} while (0)
-/* -------------------
+/*
* NUMERIC to_number() (convert string to numeric)
- * -------------------
*/
Datum
numeric_to_number(PG_FUNCTION_ARGS)
@@ -6362,9 +6311,8 @@ numeric_to_number(PG_FUNCTION_ARGS)
return result;
}
-/* ------------------
+/*
* NUMERIC to_char()
- * ------------------
*/
Datum
numeric_to_char(PG_FUNCTION_ARGS)
@@ -6490,9 +6438,8 @@ numeric_to_char(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
-/* ---------------
+/*
* INT4 to_char()
- * ---------------
*/
Datum
int4_to_char(PG_FUNCTION_ARGS)
@@ -6584,9 +6531,8 @@ int4_to_char(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
-/* ---------------
+/*
* INT8 to_char()
- * ---------------
*/
Datum
int8_to_char(PG_FUNCTION_ARGS)
@@ -6696,9 +6642,8 @@ int8_to_char(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
-/* -----------------
+/*
* FLOAT4 to_char()
- * -----------------
*/
Datum
float4_to_char(PG_FUNCTION_ARGS)
@@ -6809,9 +6754,8 @@ float4_to_char(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
-/* -----------------
+/*
* FLOAT8 to_char()
- * -----------------
*/
Datum
float8_to_char(PG_FUNCTION_ARGS)
base-commit: 762faf702c6f7292bd02705553078700d92c15f1
--
2.51.0
v1-0002-formatting.c-cleanup-Move-loop-variables-definiti.patchtext/plain; charset=UTF-8; name=v1-0002-formatting.c-cleanup-Move-loop-variables-definiti.patchDownload
From 5fac132f101843e7ccbf8edab82af956eccc5634 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 02/13] formatting.c cleanup: Move loop variables
definitions into for statement
---
src/backend/utils/adt/formatting.c | 45 ++++++++++--------------------
1 file changed, 15 insertions(+), 30 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 3adbfcd5592..92e6e86ac26 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1128,9 +1128,7 @@ index_seq_search(const char *str, const KeyWord *kw, const int *index)
static const KeySuffix *
suff_search(const char *str, const KeySuffix *suf, int type)
{
- const KeySuffix *s;
-
- for (s = suf; s->name != NULL; s++)
+ for (const KeySuffix *s = suf; s->name != NULL; s++)
{
if (s->type != type)
continue;
@@ -1865,14 +1863,13 @@ char *
asc_tolower(const char *buff, size_t nbytes)
{
char *result;
- char *p;
if (!buff)
return NULL;
result = pnstrdup(buff, nbytes);
- for (p = result; *p; p++)
+ for (char *p = result; *p; p++)
*p = pg_ascii_tolower((unsigned char) *p);
return result;
@@ -1888,14 +1885,13 @@ char *
asc_toupper(const char *buff, size_t nbytes)
{
char *result;
- char *p;
if (!buff)
return NULL;
result = pnstrdup(buff, nbytes);
- for (p = result; *p; p++)
+ for (char *p = result; *p; p++)
*p = pg_ascii_toupper((unsigned char) *p);
return result;
@@ -1911,7 +1907,6 @@ char *
asc_initcap(const char *buff, size_t nbytes)
{
char *result;
- char *p;
int wasalnum = false;
if (!buff)
@@ -1919,7 +1914,7 @@ asc_initcap(const char *buff, size_t nbytes)
result = pnstrdup(buff, nbytes);
- for (p = result; *p; p++)
+ for (char *p = result; *p; p++)
{
char c;
@@ -1994,13 +1989,12 @@ asc_toupper_z(const char *buff)
static void
dump_index(const KeyWord *k, const int *index)
{
- int i,
- count = 0,
+ int count = 0,
free_i = 0;
elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:");
- for (i = 0; i < KeyWord_INDEX_SIZE; i++)
+ for (int i = 0; i < KeyWord_INDEX_SIZE; i++)
{
if (index[i] != -1)
{
@@ -2282,7 +2276,6 @@ static int
seq_search_ascii(const char *name, const char *const *array, int *len)
{
unsigned char firstc;
- const char *const *a;
*len = 0;
@@ -2293,17 +2286,14 @@ seq_search_ascii(const char *name, const char *const *array, int *len)
/* we handle first char specially to gain some speed */
firstc = pg_ascii_tolower((unsigned char) *name);
- for (a = array; *a != NULL; a++)
+ for (const char *const *a = array; *a != NULL; a++)
{
- const char *p;
- const char *n;
-
/* compare first chars */
if (pg_ascii_tolower((unsigned char) **a) != firstc)
continue;
/* compare rest of string */
- for (p = *a + 1, n = name + 1;; p++, n++)
+ for (const char *p = *a + 1, *n = name + 1;; p++, n++)
{
/* return success if we matched whole array entry */
if (*p == '\0')
@@ -2338,7 +2328,6 @@ seq_search_ascii(const char *name, const char *const *array, int *len)
static int
seq_search_localized(const char *name, char **array, int *len, Oid collid)
{
- char **a;
char *upper_name;
char *lower_name;
@@ -2352,7 +2341,7 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid)
* The case-folding processing done below is fairly expensive, so before
* doing that, make a quick pass to see if there is an exact match.
*/
- for (a = array; *a != NULL; a++)
+ for (char **a = array; *a != NULL; a++)
{
int element_len = strlen(*a);
@@ -2371,7 +2360,7 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid)
lower_name = str_tolower(upper_name, strlen(upper_name), collid);
pfree(upper_name);
- for (a = array; *a != NULL; a++)
+ for (char **a = array; *a != NULL; a++)
{
char *upper_element;
char *lower_element;
@@ -2438,9 +2427,8 @@ from_char_seq_search(int *dest, const char **src, const char *const *array,
* any) to avoid including irrelevant data.
*/
char *copy = pstrdup(*src);
- char *c;
- for (c = copy; *c; c++)
+ for (char *c = copy; *c; c++)
{
if (scanner_isspace(*c))
{
@@ -2467,7 +2455,6 @@ from_char_seq_search(int *dest, const char **src, const char *const *array,
static void
DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
{
- FormatNode *n;
char *s;
struct fmt_tm *tm = &in->tm;
int i;
@@ -2476,7 +2463,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
cache_locale_time();
s = out;
- for (n = node; n->type != NODE_TYPE_END; n++)
+ for (FormatNode *n = node; n->type != NODE_TYPE_END; n++)
{
if (n->type != NODE_TYPE_ACTION)
{
@@ -3686,10 +3673,9 @@ DCH_prevent_counter_overflow(void)
static int
DCH_datetime_type(FormatNode *node)
{
- FormatNode *n;
int flags = 0;
- for (n = node; n->type != NODE_TYPE_END; n++)
+ for (FormatNode *n = node; n->type != NODE_TYPE_END; n++)
{
if (n->type != NODE_TYPE_ACTION)
continue;
@@ -5026,8 +5012,7 @@ int_to_roman(int number)
{
int len,
num;
- char *p,
- *result,
+ char *result,
numstr[12];
result = (char *) palloc(MAX_ROMAN_LEN + 1);
@@ -5048,7 +5033,7 @@ int_to_roman(int number)
len = snprintf(numstr, sizeof(numstr), "%d", number);
Assert(len > 0 && len <= 4);
- for (p = numstr; *p != '\0'; p++, --len)
+ for (char *p = numstr; *p != '\0'; p++, --len)
{
num = *p - ('0' + 1);
if (num < 0)
--
2.51.0
v1-0003-formatting.c-cleanup-Use-size_t-for-string-length.patchtext/plain; charset=UTF-8; name=v1-0003-formatting.c-cleanup-Use-size_t-for-string-length.patchDownload
From c34cf49b22e465c226524bcf56fa4f2c40935f3e Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 03/13] formatting.c cleanup: Use size_t for string length
variables and arguments
---
src/backend/utils/adt/formatting.c | 96 +++++++++++++++---------------
1 file changed, 48 insertions(+), 48 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 92e6e86ac26..93f497e31cb 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -118,9 +118,9 @@
typedef struct
{
const char *name; /* suffix string */
- int len, /* suffix length */
- id, /* used in node->suffix */
- type; /* prefix / postfix */
+ size_t len; /* suffix length */
+ int id; /* used in node->suffix */
+ int type; /* prefix / postfix */
} KeySuffix;
/*
@@ -139,7 +139,7 @@ typedef enum
typedef struct
{
const char *name;
- int len;
+ size_t len;
int id;
bool is_digit;
FromCharDateMode date_mode;
@@ -1058,17 +1058,17 @@ static void dump_node(FormatNode *node, int max);
static const char *get_th(char *num, int type);
static char *str_numth(char *dest, char *num, int type);
static int adjust_partial_year_to_2020(int year);
-static int strspace_len(const char *str);
+static size_t strspace_len(const char *str);
static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
Node *escontext);
static bool from_char_set_int(int *dest, const int value, const FormatNode *node,
Node *escontext);
-static int from_char_parse_int_len(int *dest, const char **src, const int len,
+static int from_char_parse_int_len(int *dest, const char **src, const size_t len,
FormatNode *node, Node *escontext);
static int from_char_parse_int(int *dest, const char **src, FormatNode *node,
Node *escontext);
-static int seq_search_ascii(const char *name, const char *const *array, int *len);
-static int seq_search_localized(const char *name, char **array, int *len,
+static int seq_search_ascii(const char *name, const char *const *array, size_t *len);
+static int seq_search_localized(const char *name, char **array, size_t *len,
Oid collid);
static bool from_char_seq_search(int *dest, const char **src,
const char *const *array,
@@ -1077,16 +1077,16 @@ static bool from_char_seq_search(int *dest, const char **src,
static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz,
int *fprec, uint32 *flags, Node *escontext);
-static char *fill_str(char *str, int c, int max);
+static char *fill_str(char *str, int c, size_t maxlen);
static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
static char *int_to_roman(int number);
-static int roman_to_int(NUMProc *Np, int input_len);
+static int roman_to_int(NUMProc *Np, size_t input_len);
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_from_char(NUMProc *Np, int id, size_t input_len);
static void NUM_numpart_to_char(NUMProc *Np, int id);
static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
- char *number, int input_len, int to_char_out_pre_spaces,
+ char *number, size_t input_len, int to_char_out_pre_spaces,
int sign, bool is_to_char, Oid collid);
static DCHCacheEntry *DCH_cache_getnew(const char *str, bool std);
static DCHCacheEntry *DCH_cache_search(const char *str, bool std);
@@ -1526,8 +1526,8 @@ dump_node(FormatNode *node, int max)
static const char *
get_th(char *num, int type)
{
- int len = strlen(num),
- last;
+ size_t len = strlen(num);
+ char last;
Assert(len > 0);
@@ -2072,10 +2072,10 @@ adjust_partial_year_to_2020(int year)
}
-static int
+static size_t
strspace_len(const char *str)
{
- int len = 0;
+ size_t len = 0;
while (*str && isspace((unsigned char) *str))
{
@@ -2158,13 +2158,13 @@ from_char_set_int(int *dest, const int value, const FormatNode *node,
* with DD and MI).
*/
static int
-from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node,
+from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNode *node,
Node *escontext)
{
long result;
char copy[DCH_MAX_ITEM_SIZ + 1];
const char *init = *src;
- int used;
+ size_t used;
/*
* Skip any whitespace before parsing the integer.
@@ -2172,7 +2172,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *
*src += strspace_len(*src);
Assert(len <= DCH_MAX_ITEM_SIZ);
- used = (int) strlcpy(copy, *src, len + 1);
+ used = strlcpy(copy, *src, len + 1);
if (S_FM(node->suffix) || is_next_separator(node))
{
@@ -2199,7 +2199,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("source string too short for \"%s\" formatting field",
node->key->name),
- errdetail("Field requires %d characters, but only %d remain.",
+ errdetail("Field requires %zu characters, but only %zu remain.",
len, used),
errhint("If your source string is not fixed-width, "
"try using the \"FM\" modifier.")));
@@ -2213,7 +2213,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid value \"%s\" for \"%s\"",
copy, node->key->name),
- errdetail("Field requires %d characters, but only %d could be parsed.",
+ errdetail("Field requires %zu characters, but only %zu could be parsed.",
len, used),
errhint("If your source string is not fixed-width, "
"try using the \"FM\" modifier.")));
@@ -2273,7 +2273,7 @@ from_char_parse_int(int *dest, const char **src, FormatNode *node,
* suitable for comparisons to ASCII strings.
*/
static int
-seq_search_ascii(const char *name, const char *const *array, int *len)
+seq_search_ascii(const char *name, const char *const *array, size_t *len)
{
unsigned char firstc;
@@ -2326,7 +2326,7 @@ seq_search_ascii(const char *name, const char *const *array, int *len)
* the arrays exported by pg_locale.c aren't const.
*/
static int
-seq_search_localized(const char *name, char **array, int *len, Oid collid)
+seq_search_localized(const char *name, char **array, size_t *len, Oid collid)
{
char *upper_name;
char *lower_name;
@@ -2343,7 +2343,7 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid)
*/
for (char **a = array; *a != NULL; a++)
{
- int element_len = strlen(*a);
+ size_t element_len = strlen(*a);
if (strncmp(name, *a, element_len) == 0)
{
@@ -2364,7 +2364,7 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid)
{
char *upper_element;
char *lower_element;
- int element_len;
+ size_t element_len;
/* Likewise upper/lower-case array element */
upper_element = str_toupper(*a, strlen(*a), collid);
@@ -2413,7 +2413,7 @@ from_char_seq_search(int *dest, const char **src, const char *const *array,
char **localized_array, Oid collid,
FormatNode *node, Node *escontext)
{
- int len;
+ size_t len;
if (localized_array == NULL)
*dest = seq_search_ascii(*src, array, &len);
@@ -3881,7 +3881,7 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
char *fmt_str,
*result;
bool incache;
- int fmt_len;
+ size_t fmt_len;
text *res;
/*
@@ -4311,7 +4311,7 @@ bool
datetime_format_has_tz(const char *fmt_str)
{
bool incache;
- int fmt_len = strlen(fmt_str);
+ size_t fmt_len = strlen(fmt_str);
int result;
FormatNode *format;
@@ -4804,10 +4804,10 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
static char *
-fill_str(char *str, int c, int max)
+fill_str(char *str, int c, size_t maxlen)
{
- memset(str, c, max);
- *(str + max) = '\0';
+ memset(str, c, maxlen);
+ *(str + maxlen) = '\0';
return str;
}
@@ -5067,10 +5067,10 @@ int_to_roman(int number)
* If input is invalid, return -1.
*/
static int
-roman_to_int(NUMProc *Np, int input_len)
+roman_to_int(NUMProc *Np, size_t input_len)
{
int result = 0;
- int len;
+ size_t len;
char romanChars[MAX_ROMAN_LEN];
int romanValues[MAX_ROMAN_LEN];
int repeatCount = 1;
@@ -5109,7 +5109,7 @@ roman_to_int(NUMProc *Np, int input_len)
return -1; /* No valid roman numerals. */
/* Check for valid combinations and compute the represented value. */
- for (int i = 0; i < len; i++)
+ for (size_t i = 0; i < len; i++)
{
char currChar = romanChars[i];
int currValue = romanValues[i];
@@ -5324,7 +5324,7 @@ get_last_relevant_decnum(char *num)
* Number extraction for TO_NUMBER()
*/
static void
-NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
+NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len)
{
bool isread = false;
@@ -5358,7 +5358,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
*/
if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE)
{
- int x = 0;
+ size_t x = 0;
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
@@ -5437,7 +5437,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
* Np->decimal is always just "." if we don't have a D format token.
* So we just unconditionally match to Np->decimal.
*/
- int x = strlen(Np->decimal);
+ size_t x = strlen(Np->decimal);
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "Try read decimal point (%c)",
@@ -5476,7 +5476,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
(Np->inout_p + 1) < Np->inout + input_len &&
!isdigit((unsigned char) *(Np->inout_p + 1)))
{
- int x;
+ size_t x;
char *tmp = Np->inout_p++;
#ifdef DEBUG_TO_FROM_CHAR
@@ -5728,7 +5728,7 @@ NUM_numpart_to_char(NUMProc *Np, int id)
* Skip over "n" input characters, but only if they aren't numeric data
*/
static void
-NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len)
+NUM_eat_non_data_chars(NUMProc *Np, int n, size_t input_len)
{
while (n-- > 0)
{
@@ -5742,14 +5742,14 @@ NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len)
static char *
NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
- char *number, int input_len, int to_char_out_pre_spaces,
+ char *number, size_t input_len, int to_char_out_pre_spaces,
int sign, bool is_to_char, Oid collid)
{
FormatNode *n;
NUMProc _Np,
*Np = &_Np;
const char *pattern;
- int pattern_len;
+ size_t pattern_len;
MemSet(Np, 0, sizeof(NUMProc));
@@ -5830,7 +5830,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
*/
if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces)
{
- int last_zero_pos;
+ size_t last_zero_pos;
char *last_zero;
/* note that Np->number cannot be zero-length here */
@@ -6222,7 +6222,7 @@ do { \
*/
#define NUM_TOCHAR_finish \
do { \
- int len; \
+ size_t len; \
\
NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \
\
@@ -6367,7 +6367,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
}
else
{
- int numstr_pre_len;
+ size_t numstr_pre_len;
Numeric val = value;
Numeric x;
@@ -6464,7 +6464,7 @@ int4_to_char(PG_FUNCTION_ARGS)
}
else
{
- int numstr_pre_len;
+ size_t numstr_pre_len;
if (IS_MULTI(&Num))
{
@@ -6573,7 +6573,7 @@ int8_to_char(PG_FUNCTION_ARGS)
}
else
{
- int numstr_pre_len;
+ size_t numstr_pre_len;
if (IS_MULTI(&Num))
{
@@ -6687,7 +6687,7 @@ float4_to_char(PG_FUNCTION_ARGS)
{
float4 val = value;
char *orgnum;
- int numstr_pre_len;
+ size_t numstr_pre_len;
if (IS_MULTI(&Num))
{
@@ -6799,7 +6799,7 @@ float8_to_char(PG_FUNCTION_ARGS)
{
float8 val = value;
char *orgnum;
- int numstr_pre_len;
+ size_t numstr_pre_len;
if (IS_MULTI(&Num))
{
--
2.51.0
v1-0004-formatting.c-cleanup-Add-some-const-char-qualifie.patchtext/plain; charset=UTF-8; name=v1-0004-formatting.c-cleanup-Add-some-const-char-qualifie.patchDownload
From 6e12166dfea398e72cee8696d906e68a07382206 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 04/13] formatting.c cleanup: Add some const char *
qualifiers
---
src/backend/utils/adt/formatting.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 93f497e31cb..d949153dfb4 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -436,7 +436,7 @@ typedef struct
bool has_tz; /* was there a TZ field? */
int gmtoffset; /* GMT offset of fixed-offset zone abbrev */
pg_tz *tzp; /* pg_tz for dynamic abbrev */
- char *abbrev; /* dynamic abbrev */
+ const char *abbrev; /* dynamic abbrev */
} TmFromChar;
#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
@@ -1055,8 +1055,8 @@ static void dump_index(const KeyWord *k, const int *index);
static void dump_node(FormatNode *node, int max);
#endif
-static const char *get_th(char *num, int type);
-static char *str_numth(char *dest, char *num, int type);
+static const char *get_th(const char *num, int type);
+static char *str_numth(char *dest, const char *num, int type);
static int adjust_partial_year_to_2020(int year);
static size_t strspace_len(const char *str);
static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
@@ -1082,7 +1082,7 @@ static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *should
static char *int_to_roman(int number);
static int roman_to_int(NUMProc *Np, size_t input_len);
static void NUM_prepare_locale(NUMProc *Np);
-static char *get_last_relevant_decnum(char *num);
+static char *get_last_relevant_decnum(const char *num);
static void NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len);
static void NUM_numpart_to_char(NUMProc *Np, int id);
static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
@@ -1524,7 +1524,7 @@ dump_node(FormatNode *node, int max)
* type --> 0 upper, 1 lower
*/
static const char *
-get_th(char *num, int type)
+get_th(const char *num, int type)
{
size_t len = strlen(num);
char last;
@@ -1570,7 +1570,7 @@ get_th(char *num, int type)
* type --> 0 upper, 1 lower
*/
static char *
-str_numth(char *dest, char *num, int type)
+str_numth(char *dest, const char *num, int type)
{
if (dest != num)
strcpy(dest, num);
@@ -5297,7 +5297,7 @@ NUM_prepare_locale(NUMProc *Np)
* behavior as if FM hadn't been specified).
*/
static char *
-get_last_relevant_decnum(char *num)
+get_last_relevant_decnum(const char *num)
{
char *result,
*p = strchr(num, '.');
--
2.51.0
v1-0005-formatting.c-cleanup-Use-array-syntax-instead-of-.patchtext/plain; charset=UTF-8; name=v1-0005-formatting.c-cleanup-Use-array-syntax-instead-of-.patchDownload
From 1f75a3249aff857049f29bbdf45d79ac0116a8a8 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 05/13] formatting.c cleanup: Use array syntax instead of
pointer arithmetic
for easier readability
---
src/backend/utils/adt/formatting.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index d949153dfb4..0671acf2874 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1109,7 +1109,7 @@ index_seq_search(const char *str, const KeyWord *kw, const int *index)
if (!KeyWord_INDEX_FILTER(*str))
return NULL;
- if ((poz = *(index + (*str - ' '))) > -1)
+ if ((poz = index[*str - ' ']) > -1)
{
const KeyWord *k = kw + poz;
@@ -1531,7 +1531,7 @@ get_th(const char *num, int type)
Assert(len > 0);
- last = *(num + (len - 1));
+ last = num[len - 1];
if (!isdigit((unsigned char) last))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
@@ -4807,7 +4807,7 @@ static char *
fill_str(char *str, int c, size_t maxlen)
{
memset(str, c, maxlen);
- *(str + maxlen) = '\0';
+ str[maxlen] = '\0';
return str;
}
--
2.51.0
v1-0006-formatting.c-cleanup-Remove-unnecessary-extra-par.patchtext/plain; charset=UTF-8; name=v1-0006-formatting.c-cleanup-Remove-unnecessary-extra-par.patchDownload
From 26970c5c4e0781305968b206261b38605afe9888 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 06/13] formatting.c cleanup: Remove unnecessary extra
parentheses
---
src/backend/utils/adt/formatting.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 0671acf2874..1a40463023c 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1200,7 +1200,7 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
break;
case NUM_B:
- if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num)))
+ if (num->pre == 0 && num->post == 0 && !IS_ZERO(num))
num->flag |= NUM_F_BLANK;
break;
@@ -1541,7 +1541,7 @@ get_th(const char *num, int type)
* All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
* 'ST/st', 'ND/nd', 'RD/rd', respectively
*/
- if ((len > 1) && (num[len - 2] == '1'))
+ if (len > 1 && num[len - 2] == '1')
last = 0;
switch (last)
--
2.51.0
v1-0007-formatting.c-cleanup-Remove-unnecessary-extra-lin.patchtext/plain; charset=UTF-8; name=v1-0007-formatting.c-cleanup-Remove-unnecessary-extra-lin.patchDownload
From 821d03e2c7b5f54d0a3ccedaacd277b4854e2f6d Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 07/13] formatting.c cleanup: Remove unnecessary extra line
breaks in error message literals
---
src/backend/utils/adt/formatting.c | 36 ++++++++++--------------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 1a40463023c..e11b01242c0 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -2106,8 +2106,7 @@ from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
ereturn(escontext, false,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid combination of date conventions"),
- errhint("Do not mix Gregorian and ISO week date "
- "conventions in a formatting template.")));
+ errhint("Do not mix Gregorian and ISO week date conventions in a formatting template.")));
}
return true;
}
@@ -2130,8 +2129,7 @@ from_char_set_int(int *dest, const int value, const FormatNode *node,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("conflicting values for \"%s\" field in formatting string",
node->key->name),
- errdetail("This value contradicts a previous setting "
- "for the same field type.")));
+ errdetail("This value contradicts a previous setting for the same field type.")));
*dest = value;
return true;
}
@@ -2201,8 +2199,7 @@ from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNod
node->key->name),
errdetail("Field requires %zu characters, but only %zu remain.",
len, used),
- errhint("If your source string is not fixed-width, "
- "try using the \"FM\" modifier.")));
+ errhint("If your source string is not fixed-width, try using the \"FM\" modifier.")));
errno = 0;
result = strtol(copy, &last, 10);
@@ -2215,8 +2212,7 @@ from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNod
copy, node->key->name),
errdetail("Field requires %zu characters, but only %zu could be parsed.",
len, used),
- errhint("If your source string is not fixed-width, "
- "try using the \"FM\" modifier.")));
+ errhint("If your source string is not fixed-width, try using the \"FM\" modifier.")));
*src += used;
}
@@ -2441,8 +2437,7 @@ from_char_seq_search(int *dest, const char **src, const char *const *array,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid value \"%s\" for \"%s\"",
copy, node->key->name),
- errdetail("The given value did not match any of "
- "the allowed values for this field.")));
+ errdetail("The given value did not match any of the allowed values for this field.")));
}
*src += len;
return true;
@@ -3337,8 +3332,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
*/
ereturn(escontext,,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid value \"%s\" for \"%s\"",
- s, n->key->name),
+ errmsg("invalid value \"%s\" for \"%s\"", s, n->key->name),
errdetail("Time zone abbreviation is not recognized.")));
}
/* otherwise parse it like OF */
@@ -3540,8 +3534,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
if (matched < 2)
ereturn(escontext,,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("invalid value \"%s\" for \"%s\"",
- s, "Y,YYY")));
+ errmsg("invalid value \"%s\" for \"%s\"", s, "Y,YYY")));
/* years += (millennia * 1000); */
if (pg_mul_s32_overflow(millennia, 1000, &millennia) ||
@@ -4114,8 +4107,7 @@ to_date(PG_FUNCTION_ARGS)
if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("date out of range: \"%s\"",
- text_to_cstring(date_txt))));
+ errmsg("date out of range: \"%s\"", text_to_cstring(date_txt))));
result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
@@ -4123,8 +4115,7 @@ to_date(PG_FUNCTION_ARGS)
if (!IS_VALID_DATE(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("date out of range: \"%s\"",
- text_to_cstring(date_txt))));
+ errmsg("date out of range: \"%s\"", text_to_cstring(date_txt))));
PG_RETURN_DATEADT(result);
}
@@ -4228,8 +4219,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("date out of range: \"%s\"",
- text_to_cstring(date_txt))));
+ errmsg("date out of range: \"%s\"", text_to_cstring(date_txt))));
result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) -
POSTGRES_EPOCH_JDATE;
@@ -4238,8 +4228,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
if (!IS_VALID_DATE(result))
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("date out of range: \"%s\"",
- text_to_cstring(date_txt))));
+ errmsg("date out of range: \"%s\"", text_to_cstring(date_txt))));
*typid = DATEOID;
return DateADTGetDatum(result);
@@ -4476,8 +4465,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
{
errsave(escontext,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
- errmsg("hour \"%d\" is invalid for the 12-hour clock",
- tm->tm_hour),
+ errmsg("hour \"%d\" is invalid for the 12-hour clock", tm->tm_hour),
errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
goto fail;
}
--
2.51.0
v1-0008-formatting.c-cleanup-Remove-unnecessary-zeroize-m.patchtext/plain; charset=UTF-8; name=v1-0008-formatting.c-cleanup-Remove-unnecessary-zeroize-m.patchDownload
From 51994d68b4a8cd52f5e3c29152aaffa4471f6f87 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 08/13] formatting.c cleanup: Remove unnecessary zeroize
macros
Replace with initializer or memset().
---
src/backend/utils/adt/formatting.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index e11b01242c0..a1d59ef859c 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -439,8 +439,6 @@ typedef struct
const char *abbrev; /* dynamic abbrev */
} TmFromChar;
-#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
-
struct fmt_tz /* do_to_timestamp's timezone info output */
{
bool has_tz; /* was there any TZ/TZH/TZM field? */
@@ -4365,7 +4363,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
int *fprec, uint32 *flags, Node *escontext)
{
FormatNode *format = NULL;
- TmFromChar tmfc;
+ TmFromChar tmfc = {0};
int fmt_len;
char *date_str;
int fmask;
@@ -4376,7 +4374,6 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
date_str = text_to_cstring(date_txt);
- ZERO_tmfc(&tmfc);
ZERO_tm(tm);
*fsec = 0;
tz->has_tz = false;
@@ -4799,19 +4796,6 @@ fill_str(char *str, int c, size_t maxlen)
return str;
}
-#define zeroize_NUM(_n) \
-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)
-
/* This works the same as DCH_prevent_counter_overflow */
static inline void
NUM_prevent_counter_overflow(void)
@@ -4919,7 +4903,7 @@ NUM_cache_fetch(const char *str)
*/
ent = NUM_cache_getnew(str);
- zeroize_NUM(&ent->Num);
+ memset(&ent->Num, 0, sizeof ent->Num);
parse_format(ent->format, str, NUM_keywords,
NULL, NUM_index, NUM_FLAG, &ent->Num);
@@ -4950,7 +4934,7 @@ NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
*shouldFree = true;
- zeroize_NUM(Num);
+ memset(Num, 0, sizeof *Num);
parse_format(format, str, NUM_keywords,
NULL, NUM_index, NUM_FLAG, Num);
--
2.51.0
v1-0009-formatting.c-cleanup-Improve-formatting-of-some-s.patchtext/plain; charset=UTF-8; name=v1-0009-formatting.c-cleanup-Improve-formatting-of-some-s.patchDownload
From 5717ddddbc7a2f9edf0700f96619ab6fb2a4c31b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 09/13] formatting.c cleanup: Improve formatting of some
struct declarations
This makes future editing easier.
---
src/backend/utils/adt/formatting.c | 64 +++++++++++++++---------------
1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index a1d59ef859c..cab3d4374c0 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -297,15 +297,15 @@ static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
*/
typedef struct
{
- int pre, /* (count) numbers before decimal */
- post, /* (count) numbers after decimal */
- lsign, /* want locales sign */
- flag, /* number parameters */
- pre_lsign_num, /* tmp value for lsign */
- multi, /* multiplier for 'V' */
- zero_start, /* position of first zero */
- zero_end, /* position of last zero */
- need_locale; /* needs it locale */
+ int pre; /* (count) numbers before decimal */
+ int post; /* (count) numbers after decimal */
+ int lsign; /* want locales sign */
+ int flag; /* number parameters */
+ int pre_lsign_num; /* tmp value for lsign */
+ int multi; /* multiplier for 'V' */
+ int zero_start; /* position of first zero */
+ int zero_end; /* position of last zero */
+ int need_locale; /* needs it locale */
} NUMDesc;
/*
@@ -410,29 +410,29 @@ static int NUMCounter = 0; /* aging-event counter */
typedef struct
{
FromCharDateMode mode;
- int hh,
- pm,
- mi,
- ss,
- ssss,
- d, /* stored as 1-7, Sunday = 1, 0 means missing */
- dd,
- ddd,
- mm,
- ms,
- year,
- bc,
- ww,
- w,
- cc,
- j,
- us,
- yysz, /* is it YY or YYYY ? */
- clock, /* 12 or 24 hour clock? */
- tzsign, /* +1, -1, or 0 if no TZH/TZM fields */
- tzh,
- tzm,
- ff; /* fractional precision */
+ int hh;
+ int pm;
+ int mi;
+ int ss;
+ int ssss;
+ int d; /* stored as 1-7, Sunday = 1, 0 means missing */
+ int dd;
+ int ddd;
+ int mm;
+ int ms;
+ int year;
+ int bc;
+ int ww;
+ int w;
+ int cc;
+ int j;
+ int us;
+ int yysz; /* is it YY or YYYY ? */
+ int clock; /* 12 or 24 hour clock? */
+ int tzsign; /* +1, -1, or 0 if no TZH/TZM fields */
+ int tzh;
+ int tzm;
+ int ff; /* fractional precision */
bool has_tz; /* was there a TZ field? */
int gmtoffset; /* GMT offset of fixed-offset zone abbrev */
pg_tz *tzp; /* pg_tz for dynamic abbrev */
--
2.51.0
v1-0010-formatting.c-cleanup-Change-TmFromChar.clock-fiel.patchtext/plain; charset=UTF-8; name=v1-0010-formatting.c-cleanup-Change-TmFromChar.clock-fiel.patchDownload
From 5c06aec1a9c00aef4042602c5c7e8a2d694e0009 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 10/13] formatting.c cleanup: Change TmFromChar.clock field
to bool
This makes the purpose clearer and avoids having two extra symbols,
one of which (CLOCK_24_HOUR) was unused.
---
src/backend/utils/adt/formatting.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index cab3d4374c0..532ed7ab2ad 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -162,9 +162,6 @@ typedef struct
#define SUFFTYPE_PREFIX 1
#define SUFFTYPE_POSTFIX 2
-#define CLOCK_24_HOUR 0
-#define CLOCK_12_HOUR 1
-
/*
* Full months
@@ -428,7 +425,7 @@ typedef struct
int j;
int us;
int yysz; /* is it YY or YYYY ? */
- int clock; /* 12 or 24 hour clock? */
+ bool clock_12_hour; /* 12 or 24 hour clock? */
int tzsign; /* +1, -1, or 0 if no TZH/TZM fields */
int tzh;
int tzm;
@@ -3225,7 +3222,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
return;
if (!from_char_set_int(&out->pm, value % 2, n, escontext))
return;
- out->clock = CLOCK_12_HOUR;
+ out->clock_12_hour = true;
break;
case DCH_AM:
case DCH_PM:
@@ -3237,13 +3234,13 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
return;
if (!from_char_set_int(&out->pm, value % 2, n, escontext))
return;
- out->clock = CLOCK_12_HOUR;
+ out->clock_12_hour = true;
break;
case DCH_HH:
case DCH_HH12:
if (from_char_parse_int_len(&out->hh, &s, 2, n, escontext) < 0)
return;
- out->clock = CLOCK_12_HOUR;
+ out->clock_12_hour = true;
SKIP_THth(s, n->suffix);
break;
case DCH_HH24:
@@ -4456,7 +4453,7 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
if (tmfc.hh)
tm->tm_hour = tmfc.hh;
- if (tmfc.clock == CLOCK_12_HOUR)
+ if (tmfc.clock_12_hour)
{
if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
{
--
2.51.0
v1-0011-formatting.c-cleanup-Change-several-int-fields-to.patchtext/plain; charset=UTF-8; name=v1-0011-formatting.c-cleanup-Change-several-int-fields-to.patchDownload
From 231ac1b944579f203a243753b5f63c521b5d6364 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 11/13] formatting.c cleanup: Change several int fields to
enums
This makes their purpose more self-documenting.
---
src/backend/utils/adt/formatting.c | 76 ++++++++++++++++++------------
1 file changed, 46 insertions(+), 30 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 532ed7ab2ad..d72e0572e32 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -115,12 +115,19 @@
/*
* Format parser structs
*/
+
+enum KeySuffixType
+{
+ SUFFTYPE_PREFIX = 1,
+ SUFFTYPE_POSTFIX = 2,
+};
+
typedef struct
{
const char *name; /* suffix string */
size_t len; /* suffix length */
int id; /* used in node->suffix */
- int type; /* prefix / postfix */
+ enum KeySuffixType type; /* prefix / postfix */
} KeySuffix;
/*
@@ -145,23 +152,23 @@ typedef struct
FromCharDateMode date_mode;
} KeyWord;
+enum FormatNodeType
+{
+ NODE_TYPE_END = 1,
+ NODE_TYPE_ACTION = 2,
+ NODE_TYPE_CHAR = 3,
+ NODE_TYPE_SEPARATOR = 4,
+ NODE_TYPE_SPACE = 5,
+};
+
typedef struct
{
- uint8 type; /* NODE_TYPE_XXX, see below */
+ enum FormatNodeType type;
char character[MAX_MULTIBYTE_CHAR_LEN + 1]; /* if type is CHAR */
- uint8 suffix; /* keyword prefix/suffix code, if any */
+ uint8 suffix; /* keyword prefix/suffix code, if any (DCH_S_*) */
const KeyWord *key; /* if type is ACTION */
} FormatNode;
-#define NODE_TYPE_END 1
-#define NODE_TYPE_ACTION 2
-#define NODE_TYPE_CHAR 3
-#define NODE_TYPE_SEPARATOR 4
-#define NODE_TYPE_SPACE 5
-
-#define SUFFTYPE_PREFIX 1
-#define SUFFTYPE_POSTFIX 2
-
/*
* Full months
@@ -286,8 +293,18 @@ static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
/*
* Flags & Options:
*/
-#define TH_UPPER 1
-#define TH_LOWER 2
+enum TH_Case
+{
+ TH_UPPER = 1,
+ TH_LOWER = 2,
+};
+
+enum NUMDesc_lsign
+{
+ NUM_LSIGN_PRE = -1,
+ NUM_LSIGN_POST = 1,
+ NUM_LSIGN_NONE = 0,
+};
/*
* Number description struct
@@ -296,13 +313,13 @@ typedef struct
{
int pre; /* (count) numbers before decimal */
int post; /* (count) numbers after decimal */
- int lsign; /* want locales sign */
- int flag; /* number parameters */
+ enum NUMDesc_lsign lsign; /* want locales sign */
+ int flag; /* number parameters (NUM_F_*) */
int pre_lsign_num; /* tmp value for lsign */
int multi; /* multiplier for 'V' */
int zero_start; /* position of first zero */
int zero_end; /* position of last zero */
- int need_locale; /* needs it locale */
+ bool need_locale; /* needs it locale */
} NUMDesc;
/*
@@ -323,10 +340,6 @@ typedef struct
#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
-
/*
* Tests
*/
@@ -553,7 +566,12 @@ do { \
#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)
+
+static inline enum TH_Case
+S_TH_TYPE(uint8 _s)
+{
+ return _s & DCH_S_TH ? TH_UPPER : TH_LOWER;
+}
/* Oracle toggles FM behavior, we don't; see docs. */
#define S_FM(_s) (((_s) & DCH_S_FM) ? 1 : 0)
@@ -1034,7 +1052,7 @@ typedef struct NUMProc
*/
static const KeyWord *index_seq_search(const char *str, const KeyWord *kw,
const int *index);
-static const KeySuffix *suff_search(const char *str, const KeySuffix *suf, int type);
+static const KeySuffix *suff_search(const char *str, const KeySuffix *suf, enum KeySuffixType type);
static bool is_separator_char(const char *str);
static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
static void parse_format(FormatNode *node, const char *str, const KeyWord *kw,
@@ -1050,8 +1068,8 @@ static void dump_index(const KeyWord *k, const int *index);
static void dump_node(FormatNode *node, int max);
#endif
-static const char *get_th(const char *num, int type);
-static char *str_numth(char *dest, const char *num, int type);
+static const char *get_th(const char *num, enum TH_Case type);
+static char *str_numth(char *dest, const char *num, enum TH_Case type);
static int adjust_partial_year_to_2020(int year);
static size_t strspace_len(const char *str);
static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
@@ -1121,7 +1139,7 @@ index_seq_search(const char *str, const KeyWord *kw, const int *index)
}
static const KeySuffix *
-suff_search(const char *str, const KeySuffix *suf, int type)
+suff_search(const char *str, const KeySuffix *suf, enum KeySuffixType type)
{
for (const KeySuffix *s = suf; s->name != NULL; s++)
{
@@ -1516,10 +1534,9 @@ dump_node(FormatNode *node, int max)
/*
* Return ST/ND/RD/TH for simple (1..9) numbers
- * type --> 0 upper, 1 lower
*/
static const char *
-get_th(const char *num, int type)
+get_th(const char *num, enum TH_Case type)
{
size_t len = strlen(num);
char last;
@@ -1562,10 +1579,9 @@ get_th(const char *num, int type)
/*
* Convert string-number to ordinal string-number
- * type --> 0 upper, 1 lower
*/
static char *
-str_numth(char *dest, const char *num, int type)
+str_numth(char *dest, const char *num, enum TH_Case type)
{
if (dest != num)
strcpy(dest, num);
--
2.51.0
v1-0012-formatting.c-cleanup-Rename-DCH_S_-to-DCH_SUFFIX_.patchtext/plain; charset=UTF-8; name=v1-0012-formatting.c-cleanup-Rename-DCH_S_-to-DCH_SUFFIX_.patchDownload
From a295ff6a49f6b9715f8f6ebd0e2035286b58acfe Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 12/13] formatting.c cleanup: Rename DCH_S_* to DCH_SUFFIX_*
For clarity. Also rename several related macros and turn them into
inline functions.
---
src/backend/utils/adt/formatting.c | 239 ++++++++++++++++-------------
1 file changed, 131 insertions(+), 108 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index d72e0572e32..c421625cf60 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -165,7 +165,8 @@ typedef struct
{
enum FormatNodeType type;
char character[MAX_MULTIBYTE_CHAR_LEN + 1]; /* if type is CHAR */
- uint8 suffix; /* keyword prefix/suffix code, if any (DCH_S_*) */
+ uint8 suffix; /* keyword prefix/suffix code, if any
+ * (DCH_SUFFIX_*) */
const KeyWord *key; /* if type is ACTION */
} FormatNode;
@@ -554,29 +555,51 @@ do { \
/*
* Suffixes (FormatNode.suffix is an OR of these codes)
*/
-#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 DCH_SUFFIX_FM 0x01
+#define DCH_SUFFIX_TH 0x02
+#define DCH_SUFFIX_th 0x04
+#define DCH_SUFFIX_SP 0x08
+#define DCH_SUFFIX_TM 0x10
/*
* Suffix tests
*/
-#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)
+static inline bool
+IS_SUFFIX_TH(uint8 _s)
+{
+ return (_s & DCH_SUFFIX_TH);
+}
+
+static inline bool
+IS_SUFFIX_th(uint8 _s)
+{
+ return (_s & DCH_SUFFIX_th);
+}
+
+static inline bool
+IS_SUFFIX_THth(uint8 _s)
+{
+ return IS_SUFFIX_TH(_s) || IS_SUFFIX_th(_s);
+}
static inline enum TH_Case
-S_TH_TYPE(uint8 _s)
+SUFFIX_TH_TYPE(uint8 _s)
{
- return _s & DCH_S_TH ? TH_UPPER : TH_LOWER;
+ return _s & DCH_SUFFIX_TH ? TH_UPPER : TH_LOWER;
}
/* Oracle toggles FM behavior, we don't; see docs. */
-#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)
+static inline bool
+IS_SUFFIX_FM(uint8 _s)
+{
+ return (_s & DCH_SUFFIX_FM);
+}
+
+static inline bool
+IS_SUFFIX_TM(uint8 _s)
+{
+ return (_s & DCH_SUFFIX_TM);
+}
/*
* Suffixes definition for DATE-TIME TO/FROM CHAR
@@ -584,13 +607,13 @@ S_TH_TYPE(uint8 _s)
#define TM_SUFFIX_LEN 2
static const KeySuffix DCH_suff[] = {
- {"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
- {"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
- {"TM", TM_SUFFIX_LEN, DCH_S_TM, SUFFTYPE_PREFIX},
- {"tm", 2, DCH_S_TM, SUFFTYPE_PREFIX},
- {"TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX},
- {"th", 2, DCH_S_th, SUFFTYPE_POSTFIX},
- {"SP", 2, DCH_S_SP, SUFFTYPE_POSTFIX},
+ {"FM", 2, DCH_SUFFIX_FM, SUFFTYPE_PREFIX},
+ {"fm", 2, DCH_SUFFIX_FM, SUFFTYPE_PREFIX},
+ {"TM", TM_SUFFIX_LEN, DCH_SUFFIX_TM, SUFFTYPE_PREFIX},
+ {"tm", 2, DCH_SUFFIX_TM, SUFFTYPE_PREFIX},
+ {"TH", 2, DCH_SUFFIX_TH, SUFFTYPE_POSTFIX},
+ {"th", 2, DCH_SUFFIX_th, SUFFTYPE_POSTFIX},
+ {"SP", 2, DCH_SUFFIX_SP, SUFFTYPE_POSTFIX},
/* last */
{NULL, 0, 0, 0}
};
@@ -1498,8 +1521,8 @@ parse_format(FormatNode *node, const char *str, const KeyWord *kw,
*/
#ifdef DEBUG_TO_FROM_CHAR
-#define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))
-#define DUMP_FM(_suf) (S_FM(_suf) ? "FM" : " ")
+#define DUMP_THth(_suf) (SUFFIX_TH(_suf) ? "TH" : (SUFFIX_th(_suf) ? "th" : " "))
+#define DUMP_FM(_suf) (SUFFIX_FM(_suf) ? "FM" : " ")
static void
dump_node(FormatNode *node, int max)
@@ -1980,11 +2003,11 @@ asc_toupper_z(const char *buff)
/*
* Skip TM / th in FROM_CHAR
*
- * If S_THth is on, skip two chars, assuming there are two available
+ * If SUFFIX_THth is on, skip two chars, assuming there are two available
*/
#define SKIP_THth(ptr, _suf) \
do { \
- if (S_THth(_suf)) \
+ if (IS_SUFFIX_THth(_suf)) \
{ \
if (*(ptr)) (ptr) += pg_mblen(ptr); \
if (*(ptr)) (ptr) += pg_mblen(ptr); \
@@ -2032,7 +2055,7 @@ is_next_separator(FormatNode *n)
if (n->type == NODE_TYPE_END)
return false;
- if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
+ if (n->type == NODE_TYPE_ACTION && IS_SUFFIX_THth(n->suffix))
return true;
/*
@@ -2183,7 +2206,7 @@ from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNod
Assert(len <= DCH_MAX_ITEM_SIZ);
used = strlcpy(copy, *src, len + 1);
- if (S_FM(node->suffix) || is_next_separator(node))
+ if (IS_SUFFIX_FM(node->suffix) || is_next_separator(node))
{
/*
* This node is in Fill Mode, or the next node is known to be a
@@ -2511,40 +2534,40 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
* display time as shown on a 12-hour clock, even for
* intervals
*/
- sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
+ sprintf(s, "%0*lld", IS_SUFFIX_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ?
(long long) (HOURS_PER_DAY / 2) :
(long long) (tm->tm_hour % (HOURS_PER_DAY / 2)));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_HH24:
- sprintf(s, "%0*lld", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
+ sprintf(s, "%0*lld", IS_SUFFIX_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
(long long) tm->tm_hour);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_MI:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
tm->tm_min);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_SS:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
tm->tm_sec);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
#define DCH_to_char_fsec(frac_fmt, frac_val) \
sprintf(s, frac_fmt, (int) (frac_val)); \
- if (S_THth(n->suffix)) \
- str_numth(s, s, S_TH_TYPE(n->suffix)); \
+ if (IS_SUFFIX_THth(n->suffix)) \
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix)); \
s += strlen(s)
case DCH_FF1: /* tenth of second */
@@ -2573,8 +2596,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
(long long) (tm->tm_hour * SECS_PER_HOUR +
tm->tm_min * SECS_PER_MINUTE +
tm->tm_sec));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_tz:
@@ -2614,7 +2637,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
sprintf(s, "%c%0*d",
(tm->tm_gmtoff >= 0) ? '+' : '-',
- S_FM(n->suffix) ? 0 : 2,
+ IS_SUFFIX_FM(n->suffix) ? 0 : 2,
abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
s += strlen(s);
if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
@@ -2652,7 +2675,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
@@ -2664,7 +2687,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
asc_toupper_z(months_full[tm->tm_mon - 1]));
s += strlen(s);
break;
@@ -2672,7 +2695,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
@@ -2684,7 +2707,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
months_full[tm->tm_mon - 1]);
s += strlen(s);
break;
@@ -2692,7 +2715,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
@@ -2704,7 +2727,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
asc_tolower_z(months_full[tm->tm_mon - 1]));
s += strlen(s);
break;
@@ -2712,7 +2735,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
@@ -2731,7 +2754,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
@@ -2750,7 +2773,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
INVALID_FOR_INTERVAL;
if (!tm->tm_mon)
break;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
@@ -2766,15 +2789,15 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
s += strlen(s);
break;
case DCH_MM:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
tm->tm_mon);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_DAY:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
@@ -2786,13 +2809,13 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
asc_toupper_z(days[tm->tm_wday]));
s += strlen(s);
break;
case DCH_Day:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
@@ -2804,13 +2827,13 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
days[tm->tm_wday]);
s += strlen(s);
break;
case DCH_day:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
@@ -2822,13 +2845,13 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
errmsg("localized string format value too long")));
}
else
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -9,
asc_tolower_z(days[tm->tm_wday]));
s += strlen(s);
break;
case DCH_DY:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
@@ -2845,7 +2868,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
break;
case DCH_Dy:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
@@ -2862,7 +2885,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
break;
case DCH_dy:
INVALID_FOR_INTERVAL;
- if (S_TM(n->suffix))
+ if (IS_SUFFIX_TM(n->suffix))
{
char *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
@@ -2879,54 +2902,54 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
break;
case DCH_DDD:
case DCH_IDDD:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : 3,
(n->key->id == DCH_DDD) ?
tm->tm_yday :
date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_DD:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : 2, tm->tm_mday);
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_D:
INVALID_FOR_INTERVAL;
sprintf(s, "%d", tm->tm_wday + 1);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_ID:
INVALID_FOR_INTERVAL;
sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_WW:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : 2,
(tm->tm_yday - 1) / 7 + 1);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_IW:
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : 2,
date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_Q:
if (!tm->tm_mon)
break;
sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_CC:
@@ -2942,25 +2965,25 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
i = tm->tm_year / 100 - 1;
}
if (i <= 99 && i >= -99)
- sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
+ sprintf(s, "%0*d", IS_SUFFIX_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
else
sprintf(s, "%d", i);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_Y_YYY:
i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
sprintf(s, "%d,%03d", i,
ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_YYYY:
case DCH_IYYY:
sprintf(s, "%0*d",
- S_FM(n->suffix) ? 0 :
+ IS_SUFFIX_FM(n->suffix) ? 0 :
(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
(n->key->id == DCH_YYYY ?
ADJUST_YEAR(tm->tm_year, is_interval) :
@@ -2968,14 +2991,14 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
tm->tm_mon,
tm->tm_mday),
is_interval)));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_YYY:
case DCH_IYY:
sprintf(s, "%0*d",
- S_FM(n->suffix) ? 0 :
+ IS_SUFFIX_FM(n->suffix) ? 0 :
(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
(n->key->id == DCH_YYY ?
ADJUST_YEAR(tm->tm_year, is_interval) :
@@ -2983,14 +3006,14 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
tm->tm_mon,
tm->tm_mday),
is_interval)) % 1000);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_YY:
case DCH_IY:
sprintf(s, "%0*d",
- S_FM(n->suffix) ? 0 :
+ IS_SUFFIX_FM(n->suffix) ? 0 :
(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
(n->key->id == DCH_YY ?
ADJUST_YEAR(tm->tm_year, is_interval) :
@@ -2998,8 +3021,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
tm->tm_mon,
tm->tm_mday),
is_interval)) % 100);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_Y:
@@ -3011,8 +3034,8 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
tm->tm_mon,
tm->tm_mday),
is_interval)) % 10);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_RM:
@@ -3067,21 +3090,21 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
mon = MONTHS_PER_YEAR - tm->tm_mon;
}
- sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
+ sprintf(s, "%*s", IS_SUFFIX_FM(n->suffix) ? 0 : -4,
months[mon]);
s += strlen(s);
}
break;
case DCH_W:
sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_J:
sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
- if (S_THth(n->suffix))
- str_numth(s, s, S_TH_TYPE(n->suffix));
+ if (IS_SUFFIX_THth(n->suffix))
+ str_numth(s, s, SUFFIX_TH_TYPE(n->suffix));
s += strlen(s);
break;
}
@@ -3432,7 +3455,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
case DCH_Month:
case DCH_month:
if (!from_char_seq_search(&value, &s, months_full,
- S_TM(n->suffix) ? localized_full_months : NULL,
+ IS_SUFFIX_TM(n->suffix) ? localized_full_months : NULL,
collid,
n, escontext))
return;
@@ -3443,7 +3466,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
case DCH_Mon:
case DCH_mon:
if (!from_char_seq_search(&value, &s, months,
- S_TM(n->suffix) ? localized_abbrev_months : NULL,
+ IS_SUFFIX_TM(n->suffix) ? localized_abbrev_months : NULL,
collid,
n, escontext))
return;
@@ -3459,7 +3482,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
case DCH_Day:
case DCH_day:
if (!from_char_seq_search(&value, &s, days,
- S_TM(n->suffix) ? localized_full_days : NULL,
+ IS_SUFFIX_TM(n->suffix) ? localized_full_days : NULL,
collid,
n, escontext))
return;
@@ -3471,7 +3494,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
case DCH_Dy:
case DCH_dy:
if (!from_char_seq_search(&value, &s, days_short,
- S_TM(n->suffix) ? localized_abbrev_days : NULL,
+ IS_SUFFIX_TM(n->suffix) ? localized_abbrev_days : NULL,
collid,
n, escontext))
return;
--
2.51.0
v1-0013-formatting.c-cleanup-Change-fill_str-return-type-.patchtext/plain; charset=UTF-8; name=v1-0013-formatting.c-cleanup-Change-fill_str-return-type-.patchDownload
From 9038f68c2877a10b6b3303e8a51fb48ec6ad6516 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 20 Oct 2025 08:16:03 +0200
Subject: [PATCH v1 13/13] formatting.c cleanup: Change fill_str() return type
to void
The return value is not used anywhere.
---
src/backend/utils/adt/formatting.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index c421625cf60..4c217d0e825 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1113,7 +1113,7 @@ static bool from_char_seq_search(int *dest, const char **src,
static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz,
int *fprec, uint32 *flags, Node *escontext);
-static char *fill_str(char *str, int c, size_t maxlen);
+static void fill_str(char *str, int c, size_t maxlen);
static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
static char *int_to_roman(int number);
static int roman_to_int(NUMProc *Np, size_t input_len);
@@ -4824,12 +4824,11 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
*********************************************************************/
-static char *
+static void
fill_str(char *str, int c, size_t maxlen)
{
memset(str, c, maxlen);
str[maxlen] = '\0';
- return str;
}
/* This works the same as DCH_prevent_counter_overflow */
--
2.51.0
On Oct 20, 2025, at 17:50, Peter Eisentraut <peter@eisentraut.org> wrote:
The file formatting.c contains some hard to read and understand code. For the attached patch series, I made a few more or less mechanical passes over it to modernize the code a bit, renamed some symbols to be clearer, adjusted some types to make things more self-documenting, removed some redundant code to make some things more compact. I hope this helps a bit.
<v1-0001-formatting.c-cleanup-Remove-dashes-in-comments.patch><v1-0002-formatting.c-cleanup-Move-loop-variables-definiti.patch><v1-0003-formatting.c-cleanup-Use-size_t-for-string-length.patch><v1-0004-formatting.c-cleanup-Add-some-const-char-qualifie.patch><v1-0005-formatting.c-cleanup-Use-array-syntax-instead-of-.patch><v1-0006-formatting.c-cleanup-Remove-unnecessary-extra-par.patch><v1-0007-formatting.c-cleanup-Remove-unnecessary-extra-lin.patch><v1-0008-formatting.c-cleanup-Remove-unnecessary-zeroize-m.patch><v1-0009-formatting.c-cleanup-Improve-formatting-of-some-s.patch><v1-0010-formatting.c-cleanup-Change-TmFromChar.clock-fiel.patch><v1-0011-formatting.c-cleanup-Change-several-int-fields-to.patch><v1-0012-formatting.c-cleanup-Rename-DCH_S_-to-DCH_SUFFIX_.patch><v1-0013-formatting.c-cleanup-Change-fill_str-return-type-.patch>
0001 - Only removes dashes from comments. No logic change. LGTM.
0002 - Moves loop variable into for, which makes function local variable list shorter, and makes it easier to see which variables will still be used after for loop. So I think that improves readability. I searched for missing occurrence, and didn’t find. So, LGTM.
0003 - Replace int with size_t wherever possible. LGTM.
0004 - Changes “char *” to “const char *” wherever possible.
I found some “text *” can be “const text *”:
```
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 4c217d0e825..cc290903bb6 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1043,7 +1043,7 @@ typedef struct NUMProc
read_post, /* to_number - number of dec. digit */
read_pre; /* to_number - number non-dec. digit */
- char *number, /* string with number */
+ char *number, /* string with number */
*number_p, /* pointer to current number position */
*inout, /* in / out buffer */
*inout_p, /* pointer to current inout position */
@@ -1110,11 +1110,11 @@ static bool from_char_seq_search(int *dest, const char **src,
const char *const *array,
char **localized_array, Oid collid,
FormatNode *node, Node *escontext);
-static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
+static bool do_to_timestamp(text *date_txt, const text *fmt, Oid collid, bool std,
struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz,
int *fprec, uint32 *flags, Node *escontext);
static void fill_str(char *str, int c, size_t maxlen);
-static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
+static FormatNode *NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *shouldFree);
static char *int_to_roman(int number);
static int roman_to_int(NUMProc *Np, size_t input_len);
static void NUM_prepare_locale(NUMProc *Np);
@@ -3902,7 +3902,7 @@ DCH_cache_fetch(const char *str, bool std)
* for formatting.
*/
static text *
-datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
+datetime_to_char_body(TmToChar *tmtc, const text *fmt, bool is_interval, Oid collid)
{
FormatNode *format;
char *fmt_str,
@@ -4394,7 +4394,7 @@ datetime_format_has_tz(const char *fmt_str)
* struct 'tm', 'fsec', struct 'tz', and 'fprec'.
*/
static bool
-do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std,
+do_to_timestamp(text *date_txt, const text *fmt, Oid collid, bool std,
struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz,
int *fprec, uint32 *flags, Node *escontext)
{
@@ -4952,7 +4952,7 @@ NUM_cache_fetch(const char *str)
* Cache routine for NUM to_char version
*/
static FormatNode *
-NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
+NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *shouldFree)
{
FormatNode *format = NULL;
char *str;
```
0005 - Replaces pointer+offset with array syntax. LGMT.
0006 - Removes unnecessary (). LGTM.
0007 - I am not convinced with this change. Combining two constant string into one causes the line too long, exceeding 80 columns.
0008 - Removes some macros. LGTM.
0009 - Improves some structure definition. LGTM.
0010 - Changes TmFromChar.clock from int to bool.
A suggestion is that maybe we can move the new field “clock_12_hour” next to “bool has_tz”, so that size of the structure is reduced by 4 bytes.
0011 - Changes some int to enum. LGTM.
0012 - Renames DCH_S_* to DCH_SUFFIX_*, make the symbols more descriptive. LGTM.
0013 - Changes fill_str() to return void.
```
-static char *
+static void
fill_str(char *str, int c, size_t maxlen)
{
memset(str, c, maxlen);
str[maxlen] = '\0';
- return str;
}
```
This function has no comment, so I am not sure what “maxlen” exactly mean. Usually, we do “str[maxlen-1] = ‘\0’ because maxlen usually implies max length of the buffer. But this function seems to fill maxlen of c into str, then “maxlen” might not be a good name, “count” could be better.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
On 20.10.25 15:31, Chao Li wrote:
On Oct 20, 2025, at 17:50, Peter Eisentraut <peter@eisentraut.org> wrote:
The file formatting.c contains some hard to read and understand code. For the attached patch series, I made a few more or less mechanical passes over it to modernize the code a bit, renamed some symbols to be clearer, adjusted some types to make things more self-documenting, removed some redundant code to make some things more compact. I hope this helps a bit.
I have committed this patch set. Thanks for checking.
0004 - Changes “char *” to “const char *” wherever possible.
I found some “text *” can be “const text *”:
I added those.
0007 - I am not convinced with this change. Combining two constant string into one causes the line too long, exceeding 80 columns.
We have been moving toward not breaking up string literals, except where
they contain a line break. This makes it easier to grep for error
messages, for example.
0010 - Changes TmFromChar.clock from int to bool.
A suggestion is that maybe we can move the new field “clock_12_hour” next to “bool has_tz”, so that size of the structure is reduced by 4 bytes.
I don't think we need to worry about structure size here. (If we did,
we could change many fields to short int, probably.) The current order
seems pretty logical. So I kept it.
0013 - Changes fill_str() to return void.
```
-static char *
+static void
fill_str(char *str, int c, size_t maxlen)
{
memset(str, c, maxlen);
str[maxlen] = '\0';
- return str;
}
```This function has no comment, so I am not sure what “maxlen” exactly mean. Usually, we do “str[maxlen-1] = ‘\0’ because maxlen usually implies max length of the buffer. But this function seems to fill maxlen of c into str, then “maxlen” might not be a good name, “count” could be better.
Yes, this is a bit confusing. I added a function comment to explain this.