formatting.c cleanup

Started by Peter Eisentraut3 months ago3 messages
#1Peter Eisentraut
peter@eisentraut.org
13 attachment(s)

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

#2Chao Li
li.evan.chao@gmail.com
In reply to: Peter Eisentraut (#1)
Re: formatting.c cleanup

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/

#3Peter Eisentraut
peter@eisentraut.org
In reply to: Chao Li (#2)
Re: formatting.c cleanup

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.